From d5a706e47e581976a757bf13c3e29b1c55c3375f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 30 Mar 2017 17:13:25 +0100 Subject: [PATCH] better behaviour for truncated PNG files truncated PNG files failed with an error, even if --fail was not set ... instead, just warn, and only error out if fail is on see https://github.com/jcupitt/libvips/issues/629 --- ChangeLog | 3 +++ configure.ac | 6 ++--- libvips/deprecated/im_png2vips.c | 2 +- libvips/foreign/pforeign.h | 8 +++--- libvips/foreign/pngload.c | 4 +-- libvips/foreign/vipspng.c | 45 ++++++++++++++++++++------------ 6 files changed, 41 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index cb88ff16..633a60b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +25/3/17 started 8.5.2 +- better behaviour for truncated PNG files, thanks Yury + 25/3/17 started 8.5.1 - init more classes earlier, thanks David diff --git a/configure.ac b/configure.ac index 466304aa..68f79789 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # also update the version number in the m4 macros below -AC_INIT([vips], [8.5.1], [vipsip@jiscmail.ac.uk]) +AC_INIT([vips], [8.5.2], [vipsip@jiscmail.ac.uk]) # required for gobject-introspection AC_PREREQ(2.62) @@ -18,7 +18,7 @@ AC_CONFIG_MACRO_DIR([m4]) # user-visible library versioning m4_define([vips_major_version], [8]) m4_define([vips_minor_version], [5]) -m4_define([vips_micro_version], [1]) +m4_define([vips_micro_version], [2]) m4_define([vips_version], [vips_major_version.vips_minor_version.vips_micro_version]) @@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date` # binary interface changes not backwards compatible?: reset age to 0 LIBRARY_CURRENT=49 -LIBRARY_REVISION=1 +LIBRARY_REVISION=2 LIBRARY_AGE=7 # patched into include/vips/version.h diff --git a/libvips/deprecated/im_png2vips.c b/libvips/deprecated/im_png2vips.c index 61eb7fef..a1b24579 100644 --- a/libvips/deprecated/im_png2vips.c +++ b/libvips/deprecated/im_png2vips.c @@ -87,7 +87,7 @@ png2vips( const char *name, IMAGE *out, gboolean header_only ) return( -1 ); } else { - if( vips__png_read( filename, out ) ) + if( vips__png_read( filename, out, TRUE ) ) return( -1 ); } #else diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 358102c4..2b0f207f 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -177,15 +177,15 @@ int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out, gboolean header_only, int shrink, int fail, gboolean autorotate ); int vips__png_header( const char *name, VipsImage *out ); -int vips__png_read( const char *name, VipsImage *out ); +int vips__png_read( const char *name, VipsImage *out, gboolean fail ); gboolean vips__png_ispng_buffer( const void *buf, size_t len ); int vips__png_ispng( const char *filename ); gboolean vips__png_isinterlaced( const char *filename ); gboolean vips__png_isinterlaced_buffer( const void *buffer, size_t length ); extern const char *vips__png_suffs[]; -int vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out ); -int vips__png_header_buffer( const void *buffer, size_t length, - VipsImage *out ); +int vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out, + gboolean fail ); +int vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ); int vips__png_write( VipsImage *in, const char *filename, int compress, int interlace, const char *profile, diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index 01ffb7f1..ce805830 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -106,7 +106,7 @@ vips_foreign_load_png_load( VipsForeignLoad *load ) { VipsForeignLoadPng *png = (VipsForeignLoadPng *) load; - if( vips__png_read( png->filename, load->real ) ) + if( vips__png_read( png->filename, load->real, load->fail ) ) return( -1 ); return( 0 ); @@ -201,7 +201,7 @@ vips_foreign_load_png_buffer_load( VipsForeignLoad *load ) VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load; if( vips__png_read_buffer( buffer->buf->data, buffer->buf->length, - load->real ) ) + load->real, load->fail ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 9925ebe9..df3716bc 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -61,6 +61,8 @@ * - invalidate operation on read error * 27/2/17 * - use dbuf for buffer output + * 30/3/17 + * - better behaviour for truncated png files, thanks Yury */ /* @@ -125,8 +127,8 @@ user_error_function( png_structp png_ptr, png_const_charp error_msg ) /* This function must not return or the default error handler will be * invoked. - */ longjmp( png_jmpbuf( png_ptr ), -1 ); + */ } static void @@ -140,6 +142,7 @@ user_warning_function( png_structp png_ptr, png_const_charp warning_msg ) typedef struct { char *name; VipsImage *out; + gboolean fail; int y_pos; png_structp pPng; @@ -176,7 +179,7 @@ read_close_cb( VipsImage *out, Read *read ) } static Read * -read_new( VipsImage *out ) +read_new( VipsImage *out, gboolean fail ) { Read *read; @@ -184,6 +187,7 @@ read_new( VipsImage *out ) return( NULL ); read->name = NULL; + read->fail = fail; read->out = out; read->y_pos = 0; read->pPng = NULL; @@ -221,11 +225,11 @@ read_new( VipsImage *out ) } static Read * -read_new_filename( VipsImage *out, const char *name ) +read_new_filename( VipsImage *out, const char *name, gboolean fail ) { Read *read; - if( !(read = read_new( out )) ) + if( !(read = read_new( out, fail )) ) return( NULL ); read->name = vips_strdup( VIPS_OBJECT( out ), name ); @@ -437,7 +441,7 @@ vips__png_header( const char *name, VipsImage *out ) { Read *read; - if( !(read = read_new_filename( out, name )) || + if( !(read = read_new_filename( out, name, TRUE )) || png2vips_header( read, out ) ) return( -1 ); @@ -539,10 +543,15 @@ png2vips_generate( VipsRegion *or, read->y_pos += 1; } - /* Turn errors back on. png_read_end() can trigger them too. + /* Turn errors back on. png_read_end() can trigger them too, for + * example for a truncated file. */ - if( setjmp( png_jmpbuf( read->pPng ) ) ) - return( -1 ); + if( setjmp( png_jmpbuf( read->pPng ) ) ) { + if( read->fail ) + return( -1 ); + + return( 0 ); + } /* We need to shut down the reader immediately at the end of read or * we won't detach ready for the next image. @@ -566,7 +575,7 @@ vips__png_isinterlaced( const char *filename ) int interlace_type; image = vips_image_new(); - if( !(read = read_new_filename( image, filename )) ) { + if( !(read = read_new_filename( image, filename, TRUE )) ) { g_object_unref( image ); return( -1 ); } @@ -610,7 +619,7 @@ png2vips_image( Read *read, VipsImage *out ) } int -vips__png_read( const char *filename, VipsImage *out ) +vips__png_read( const char *filename, VipsImage *out, gboolean fail ) { Read *read; @@ -618,7 +627,7 @@ vips__png_read( const char *filename, VipsImage *out ) printf( "vips__png_read: reading \"%s\"\n", filename ); #endif /*DEBUG*/ - if( !(read = read_new_filename( out, filename )) || + if( !(read = read_new_filename( out, filename, fail )) || png2vips_image( read, out ) ) return( -1 ); @@ -665,11 +674,12 @@ vips_png_read_buffer( png_structp pPng, png_bytep data, png_size_t length ) } static Read * -read_new_buffer( VipsImage *out, const void *buffer, size_t length ) +read_new_buffer( VipsImage *out, const void *buffer, size_t length, + gboolean fail ) { Read *read; - if( !(read = read_new( out )) ) + if( !(read = read_new( out, fail )) ) return( NULL ); read->length = length; @@ -695,7 +705,7 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length )) || + if( !(read = read_new_buffer( out, buffer, length, TRUE )) || png2vips_header( read, out ) ) return( -1 ); @@ -703,11 +713,12 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ) } int -vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out ) +vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out, + gboolean fail ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length )) || + if( !(read = read_new_buffer( out, buffer, length, fail )) || png2vips_image( read, out ) ) return( -1 ); @@ -726,7 +737,7 @@ vips__png_isinterlaced_buffer( const void *buffer, size_t length ) image = vips_image_new(); - if( !(read = read_new_buffer( image, buffer, length )) ) { + if( !(read = read_new_buffer( image, buffer, length, TRUE )) ) { g_object_unref( image ); return( -1 ); }