png read fixes

- call png_read_end()
- catch errors during header read
- free read mem sooner
This commit is contained in:
John Cupitt 2014-06-23 09:49:23 +01:00
parent 150927a27f
commit 6ad65fbb68

View File

@ -146,7 +146,7 @@ typedef struct {
} Read; } Read;
static void static void
read_destroy( VipsImage *out, Read *read ) read_destroy( Read *read )
{ {
VIPS_FREEF( fclose, read->fp ); VIPS_FREEF( fclose, read->fp );
if( read->pPng ) if( read->pPng )
@ -154,6 +154,12 @@ read_destroy( VipsImage *out, Read *read )
VIPS_FREE( read->row_pointer ); VIPS_FREE( read->row_pointer );
} }
static void
read_close_cb( VipsImage *out, Read *read )
{
read_destroy( read );
}
static Read * static Read *
read_new( VipsImage *out, gboolean readbehind ) read_new( VipsImage *out, gboolean readbehind )
{ {
@ -175,7 +181,7 @@ read_new( VipsImage *out, gboolean readbehind )
read->read_pos = 0; read->read_pos = 0;
g_signal_connect( out, "close", g_signal_connect( out, "close",
G_CALLBACK( read_destroy ), read ); G_CALLBACK( read_close_cb ), read );
if( !(read->pPng = png_create_read_struct( if( !(read->pPng = png_create_read_struct(
PNG_LIBPNG_VER_STRING, NULL, PNG_LIBPNG_VER_STRING, NULL,
@ -206,6 +212,11 @@ read_new_filename( VipsImage *out, const char *name, gboolean readbehind )
if( !(read->fp = vips__file_open_read( name, NULL, FALSE )) ) if( !(read->fp = vips__file_open_read( name, NULL, FALSE )) )
return( NULL ); return( NULL );
/* Catch PNG errors from png_read_info().
*/
if( setjmp( png_jmpbuf( read->pPng ) ) )
return( NULL );
/* Read enough of the file that png_get_interlace_type() will start /* Read enough of the file that png_get_interlace_type() will start
* working. * working.
*/ */
@ -427,6 +438,10 @@ png2vips_interlace( Read *read, VipsImage *out )
png_read_image( read->pPng, read->row_pointer ); png_read_image( read->pPng, read->row_pointer );
png_read_end( read->pPng, NULL );
read_destroy( read );
return( 0 ); return( 0 );
} }
@ -481,6 +496,14 @@ png2vips_generate( VipsRegion *or,
read->y_pos += 1; read->y_pos += 1;
} }
/* We need to shut down the reader immediately at the end of read or
* we won't detach ready for the next image.
*/
if( read->y_pos >= read->out->Ysize ) {
png_read_end( read->pPng, NULL );
read_destroy( read );
}
return( 0 ); return( 0 );
} }
@ -565,7 +588,7 @@ int
vips__png_ispng_buffer( void *buf, size_t len ) vips__png_ispng_buffer( void *buf, size_t len )
{ {
if( len >= 8 && if( len >= 8 &&
!png_sig_cmp( buf, 0, 8 ) ) !png_sig_cmp( (png_bytep) buf, 0, 8 ) )
return( TRUE ); return( TRUE );
return( FALSE ); return( FALSE );
@ -610,6 +633,11 @@ read_new_buffer( VipsImage *out, char *buffer, size_t length,
png_set_read_fn( read->pPng, read, vips_png_read_buffer ); png_set_read_fn( read->pPng, read, vips_png_read_buffer );
/* Catch PNG errors from png_read_info().
*/
if( setjmp( png_jmpbuf( read->pPng ) ) )
return( NULL );
/* Read enough of the file that png_get_interlace_type() will start /* Read enough of the file that png_get_interlace_type() will start
* working. * working.
*/ */
@ -970,6 +998,8 @@ vips__png_write_buf( VipsImage *in,
return( -1 ); return( -1 );
} }
write_finish( write );
*obuf = wbuf->buf; *obuf = wbuf->buf;
wbuf->buf = NULL; wbuf->buf = NULL;
if( olen ) if( olen )