You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "Timo Boehme (JIRA)" <ji...@apache.org> on 2009/03/19 10:49:50 UTC
[jira] Created: (PDFBOX-443) Wrong length in stream decoding after
exception (results in endless loop)
Wrong length in stream decoding after exception (results in endless loop)
-------------------------------------------------------------------------
Key: PDFBOX-443
URL: https://issues.apache.org/jira/browse/PDFBOX-443
Project: PDFBox
Issue Type: Bug
Components: Parsing
Affects Versions: 0.8.0-incubator
Environment: all
Reporter: Timo Boehme
When reading streams from PDF files PDFBox may get stuck and don't return. This happens for instance if a stream with FlateDecode filter is read but flate decoder is unable to read encoded data.
The reason is that in COSStream in method doDecode(COSName, int) the filter is first applied using length specified by PDF and in case of an error the filter is applied with length parameter set to 'writtenLength'. However 'writtenLength' is read from unfilteredStream which was newly created in first try - so written length is 0 which results in some endless loop in flate decoder.
The solution: read written length before first try and (in case we have several filter) make sure that writtenLength is not 0.
The fixed method:
private void doDecode( COSName filterName, int filterIndex ) throws IOException
{
FilterManager manager = getFilterManager();
Filter filter = manager.getFilter( filterName );
InputStream input;
boolean done = false;
IOException exception = null;
long position = unFilteredStream.getPosition();
long length = unFilteredStream.getLength();
long writtenLength = unFilteredStream.getLengthWritten(); // TB: in case we need it later
if( length == 0 )
{
//if the length is zero then don't bother trying to decode
//some filters don't work when attempting to decode
//with a zero length stream. See zlib_error_01.pdf
unFilteredStream = new RandomAccessFileOutputStream( file );
done = true;
}
else
{
//ok this is a simple hack, sometimes we read a couple extra
//bytes that shouldn't be there, so we encounter an error we will just
//try again with one less byte.
for( int tryCount=0; !done && tryCount<5; tryCount++ )
{
try
{
input = new BufferedInputStream(
new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
unFilteredStream = new RandomAccessFileOutputStream( file );
filter.decode( input, unFilteredStream, this, filterIndex );
done = true;
}
catch( IOException io )
{
length--;
exception = io;
}
}
if( !done )
{
//if no good stream was found then lets try again but with the
//length of data that was actually read and not length
//defined in the dictionary
length = writtenLength;
if( length != 0 )
{
for( int tryCount=0; !done && tryCount<5; tryCount++ )
{
try
{
input = new BufferedInputStream(
new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
unFilteredStream = new RandomAccessFileOutputStream( file );
filter.decode( input, unFilteredStream, this, filterIndex );
done = true;
}
catch( IOException io )
{
length--;
exception = io;
}
}
}
}
}
if( !done )
{
throw exception;
}
}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (PDFBOX-443) Wrong length in stream decoding
after exception (results in endless loop)
Posted by "Timo Boehme (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/PDFBOX-443?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12689435#action_12689435 ]
Timo Boehme commented on PDFBOX-443:
------------------------------------
Unfortunately not since I encountered the bug by mistake: I processed PDF files without doing decryption. Thus for documents which were encrypted the flat decode would fail producing the described error. So a test case would be an encrypted document with flate compressed streams which is processed without decryption and one of the streams is read via getUnfilteredStream().
> Wrong length in stream decoding after exception (results in endless loop)
> -------------------------------------------------------------------------
>
> Key: PDFBOX-443
> URL: https://issues.apache.org/jira/browse/PDFBOX-443
> Project: PDFBox
> Issue Type: Bug
> Components: Parsing
> Affects Versions: 0.8.0-incubator
> Environment: all
> Reporter: Timo Boehme
> Original Estimate: 0.08h
> Remaining Estimate: 0.08h
>
> When reading streams from PDF files PDFBox may get stuck and don't return. This happens for instance if a stream with FlateDecode filter is read but flate decoder is unable to read encoded data.
> The reason is that in COSStream in method doDecode(COSName, int) the filter is first applied using length specified by PDF and in case of an error the filter is applied with length parameter set to 'writtenLength'. However 'writtenLength' is read from unfilteredStream which was newly created in first try - so written length is 0 which results in some endless loop in flate decoder.
> The solution: read written length before first try and (in case we have several filter) make sure that writtenLength is not 0.
> The fixed method:
> private void doDecode( COSName filterName, int filterIndex ) throws IOException
> {
> FilterManager manager = getFilterManager();
> Filter filter = manager.getFilter( filterName );
> InputStream input;
> boolean done = false;
> IOException exception = null;
> long position = unFilteredStream.getPosition();
> long length = unFilteredStream.getLength();
> long writtenLength = unFilteredStream.getLengthWritten(); // TB: in case we need it later
> if( length == 0 )
> {
> //if the length is zero then don't bother trying to decode
> //some filters don't work when attempting to decode
> //with a zero length stream. See zlib_error_01.pdf
> unFilteredStream = new RandomAccessFileOutputStream( file );
> done = true;
> }
> else
> {
> //ok this is a simple hack, sometimes we read a couple extra
> //bytes that shouldn't be there, so we encounter an error we will just
> //try again with one less byte.
> for( int tryCount=0; !done && tryCount<5; tryCount++ )
> {
> try
> {
> input = new BufferedInputStream(
> new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
> unFilteredStream = new RandomAccessFileOutputStream( file );
> filter.decode( input, unFilteredStream, this, filterIndex );
> done = true;
> }
> catch( IOException io )
> {
> length--;
> exception = io;
> }
> }
> if( !done )
> {
> //if no good stream was found then lets try again but with the
> //length of data that was actually read and not length
> //defined in the dictionary
> length = writtenLength;
> if( length != 0 )
> {
> for( int tryCount=0; !done && tryCount<5; tryCount++ )
> {
> try
> {
> input = new BufferedInputStream(
> new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
> unFilteredStream = new RandomAccessFileOutputStream( file );
> filter.decode( input, unFilteredStream, this, filterIndex );
> done = true;
> }
> catch( IOException io )
> {
> length--;
> exception = io;
> }
> }
> }
> }
> }
> if( !done )
> {
> throw exception;
> }
> }
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (PDFBOX-443) Wrong length in stream decoding
after exception (results in endless loop)
Posted by "Andreas Lehmkühler (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/PDFBOX-443?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12689418#action_12689418 ]
Andreas Lehmkühler commented on PDFBOX-443:
-------------------------------------------
I've commited Timos suggested changes with version 758577. Thanks for that.
@Timo: do you have a sample file to test fix? The solution is obvious but testing gives us a more better feeling ;-)
> Wrong length in stream decoding after exception (results in endless loop)
> -------------------------------------------------------------------------
>
> Key: PDFBOX-443
> URL: https://issues.apache.org/jira/browse/PDFBOX-443
> Project: PDFBox
> Issue Type: Bug
> Components: Parsing
> Affects Versions: 0.8.0-incubator
> Environment: all
> Reporter: Timo Boehme
> Original Estimate: 0.08h
> Remaining Estimate: 0.08h
>
> When reading streams from PDF files PDFBox may get stuck and don't return. This happens for instance if a stream with FlateDecode filter is read but flate decoder is unable to read encoded data.
> The reason is that in COSStream in method doDecode(COSName, int) the filter is first applied using length specified by PDF and in case of an error the filter is applied with length parameter set to 'writtenLength'. However 'writtenLength' is read from unfilteredStream which was newly created in first try - so written length is 0 which results in some endless loop in flate decoder.
> The solution: read written length before first try and (in case we have several filter) make sure that writtenLength is not 0.
> The fixed method:
> private void doDecode( COSName filterName, int filterIndex ) throws IOException
> {
> FilterManager manager = getFilterManager();
> Filter filter = manager.getFilter( filterName );
> InputStream input;
> boolean done = false;
> IOException exception = null;
> long position = unFilteredStream.getPosition();
> long length = unFilteredStream.getLength();
> long writtenLength = unFilteredStream.getLengthWritten(); // TB: in case we need it later
> if( length == 0 )
> {
> //if the length is zero then don't bother trying to decode
> //some filters don't work when attempting to decode
> //with a zero length stream. See zlib_error_01.pdf
> unFilteredStream = new RandomAccessFileOutputStream( file );
> done = true;
> }
> else
> {
> //ok this is a simple hack, sometimes we read a couple extra
> //bytes that shouldn't be there, so we encounter an error we will just
> //try again with one less byte.
> for( int tryCount=0; !done && tryCount<5; tryCount++ )
> {
> try
> {
> input = new BufferedInputStream(
> new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
> unFilteredStream = new RandomAccessFileOutputStream( file );
> filter.decode( input, unFilteredStream, this, filterIndex );
> done = true;
> }
> catch( IOException io )
> {
> length--;
> exception = io;
> }
> }
> if( !done )
> {
> //if no good stream was found then lets try again but with the
> //length of data that was actually read and not length
> //defined in the dictionary
> length = writtenLength;
> if( length != 0 )
> {
> for( int tryCount=0; !done && tryCount<5; tryCount++ )
> {
> try
> {
> input = new BufferedInputStream(
> new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
> unFilteredStream = new RandomAccessFileOutputStream( file );
> filter.decode( input, unFilteredStream, this, filterIndex );
> done = true;
> }
> catch( IOException io )
> {
> length--;
> exception = io;
> }
> }
> }
> }
> }
> if( !done )
> {
> throw exception;
> }
> }
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.