From 646f2d7fd7b927fdbe09053fc68b751003f63966 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 24 Jan 2022 11:27:22 +0000 Subject: [PATCH] Fix read from pipe with variable chunk sizes free the header cache only once it's exhausted --- libvips/foreign/jpeg2vips.c | 11 ++++++----- libvips/iofuncs/source.c | 15 +++++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 925c9977..318fcd5f 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -244,7 +244,7 @@ source_fill_input_buffer( j_decompress_ptr cinfo ) Source *src = (Source *) cinfo->src; size_t read; - + if( (read = vips_source_read( src->source, src->buf, SOURCE_BUFFER_SIZE )) > 0 ) { src->pub.next_input_byte = src->buf; @@ -861,6 +861,11 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out ) if( read_jpeg_header( jpeg, t[0] ) ) return( -1 ); + /* Switch to pixel decode. + */ + if( vips_source_decode( jpeg->source ) ) + return( -1 ); + jpeg_start_decompress( cinfo ); #ifdef DEBUG @@ -967,10 +972,6 @@ vips__jpeg_read_source( VipsSource *source, VipsImage *out, if( header_only ) vips_source_minimise( source ); - else { - if( vips_source_decode( source ) ) - return( -1 ); - } return( 0 ); } diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index 7520d9ef..5cb9e9e0 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -664,13 +664,12 @@ vips_source_decode( VipsSource *source ) if( !source->decode ) { source->decode = TRUE; + VIPS_FREEF( g_byte_array_unref, source->sniff ); - /* If this is still a pipe source, we can discard the header - * bytes we saved. + /* Now decode is set, header_bytes will be freed once it's + * exhausted, see vips_source_read(). */ - if( source->is_pipe ) - VIPS_FREEF( g_byte_array_unref, source->header_bytes ); } vips_source_minimise( source ); @@ -766,6 +765,14 @@ vips_source_read( VipsSource *source, void *buffer, size_t length ) total_read += available; } + /* We're in pixel decode mode and we've exhausted the header + * cache. We can safely junk it. + */ + if( source->decode && + source->header_bytes && + source->read_position >= source->header_bytes->len ) + VIPS_FREEF( g_byte_array_unref, source->header_bytes ); + /* Any more bytes requested? Call the read() vfunc. */ if( length > 0 ) {