You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "Andreas Lehmkühler (JIRA)" <ji...@apache.org> on 2009/03/26 11:17:59 UTC

[jira] Commented: (PDFBOX-443) Wrong length in stream decoding after exception (results in endless loop)

    [ 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.