From 0131d4d3ebb95e2fea4f5023f0bddbebe51acb9d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 19 Oct 2020 14:34:02 +0100 Subject: [PATCH] fix vips7 webp load webp load using the vips7 interface was crashing, thanks barryspearce see https://github.com/libvips/libvips/issues/1860 --- ChangeLog | 1 + libvips/foreign/webp2vips.c | 40 ++++++++++++++++++------------------- libvips/iofuncs/source.c | 10 +++++----- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d95d62e..3296e28c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 18/10/20 started 8.10.3 - relax heic is_a rules [hisham] +- fix vips7 webp load [barryspearce] 6/9/20 started 8.10.2 - update magicksave/load profile handling [kelilevi] diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index bb2b6c48..309130a8 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -81,6 +81,7 @@ /* What we track during a read. */ typedef struct { + VipsImage *out; VipsSource *source; /* The data we load, as a webp object. @@ -340,14 +341,21 @@ read_free( Read *read ) return( 0 ); } +static void +read_close_cb( VipsImage *image, Read *read ) +{ + read_free( read ); +} + static Read * -read_new( VipsSource *source, int page, int n, double scale ) +read_new( VipsImage *out, VipsSource *source, int page, int n, double scale ) { Read *read; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); + read->out = out; read->source = source; g_object_ref( source ); read->page = page; @@ -359,15 +367,19 @@ read_new( VipsSource *source, int page, int n, double scale ) read->dispose_method = WEBP_MUX_DISPOSE_NONE; read->frame_no = 0; + /* Everything has to stay open until read has finished, unfortunately, + * since webp relies on us mapping the whole file. + */ + g_signal_connect( out, "close", + G_CALLBACK( read_close_cb ), read ); + WebPInitDecoderConfig( &read->config ); read->config.options.use_threads = 1; read->config.output.is_external_memory = 1; if( !(read->data.bytes = - vips_source_map( source, &read->data.size )) ) { - read_free( read ); + vips_source_map( source, &read->data.size )) ) return( NULL ); - } return( read ); } @@ -774,16 +786,10 @@ vips__webp_read_header_source( VipsSource *source, VipsImage *out, { Read *read; - if( !(read = read_new( source, page, n, scale )) ) + if( !(read = read_new( out, source, page, n, scale )) || + read_header( read, out ) ) return( -1 ); - if( read_header( read, out ) ) { - read_free( read ); - return( -1 ); - } - - read_free( read ); - return( 0 ); } @@ -793,16 +799,10 @@ vips__webp_read_source( VipsSource *source, VipsImage *out, { Read *read; - if( !(read = read_new( source, page, n, scale )) ) + if( !(read = read_new( out, source, page, n, scale )) || + read_image( read, out ) ) return( -1 ); - if( read_image( read, out ) ) { - read_free( read ); - return( -1 ); - } - - read_free( read ); - return( 0 ); } diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index cd0eb73c..4989e458 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -260,6 +260,8 @@ vips_source_finalize( GObject *gobject ) { VipsSource *source = VIPS_SOURCE( gobject ); + VIPS_DEBUG_MSG( "vips_source_finalize: %p\n", source ); + VIPS_FREEF( g_byte_array_unref, source->header_bytes ); VIPS_FREEF( g_byte_array_unref, source->sniff ); if( source->mmap_baseaddr ) { @@ -555,8 +557,6 @@ vips_source_minimise( VipsSource *source ) { VipsConnection *connection = VIPS_CONNECTION( source ); - VIPS_DEBUG_MSG( "vips_source_minimise:\n" ); - SANITY( source ); (void) vips_source_test_features( source ); @@ -565,7 +565,7 @@ vips_source_minimise( VipsSource *source ) connection->descriptor != -1 && connection->tracked_descriptor == connection->descriptor && !source->is_pipe ) { - VIPS_DEBUG_MSG( " tracked_close()\n" ); + VIPS_DEBUG_MSG( "vips_source_minimise:\n" ); vips_tracked_close( connection->tracked_descriptor ); connection->tracked_descriptor = -1; connection->descriptor = -1; @@ -590,13 +590,13 @@ vips_source_unminimise( VipsSource *source ) { VipsConnection *connection = VIPS_CONNECTION( source ); - VIPS_DEBUG_MSG( "vips_source_unminimise:\n" ); - if( connection->descriptor == -1 && connection->tracked_descriptor == -1 && connection->filename ) { int fd; + VIPS_DEBUG_MSG( "vips_source_unminimise: %p\n", source ); + if( (fd = vips_tracked_open( connection->filename, MODE_READ, 0 )) == -1 ) { vips_error_system( errno,