diff --git a/ChangeLog b/ChangeLog index 7fe89781..60d1e7c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 14/7/21 started 8.11.3 - build threadpool later [kleisauke] - add jxlsave prototypes [adil-benameur] +- limit text chunks in PNGs [randy408] 15/6/20 started 8.11.2 - better libdir guessing [remi] diff --git a/libvips/foreign/spngload.c b/libvips/foreign/spngload.c index 044110ff..d339ad70 100644 --- a/libvips/foreign/spngload.c +++ b/libvips/foreign/spngload.c @@ -194,9 +194,11 @@ vips_foreign_load_png_set_text( VipsImage *out, } } -static void +static int vips_foreign_load_png_set_header( VipsForeignLoadPng *png, VipsImage *image ) { + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( png ); + double xres, yres; struct spng_iccp iccp; struct spng_exif exif; @@ -243,6 +245,15 @@ vips_foreign_load_png_set_header( VipsForeignLoadPng *png, VipsImage *image ) if( !spng_get_text( png->ctx, NULL, &n_text ) ) { struct spng_text *text; + /* Very large numbers of text chunks are used in DoS + * attacks. + */ + if( n_text > 10 ) { + vips_error( class->nickname, + "%s", _( "too many text chunks" ) ); + return( -1 ); + } + text = VIPS_ARRAY( VIPS_OBJECT( png ), n_text, struct spng_text ); if( !spng_get_text( png->ctx, text, &n_text ) ) { @@ -306,6 +317,8 @@ vips_foreign_load_png_set_header( VipsForeignLoadPng *png, VipsImage *image ) vips_image_set_array_double( image, "background", array, n ); } + + return( 0 ); } static int @@ -455,7 +468,8 @@ vips_foreign_load_png_header( VipsForeignLoad *load ) vips_source_minimise( png->source ); - vips_foreign_load_png_set_header( png, load->out ); + if( vips_foreign_load_png_set_header( png, load->out ) ) + return( -1 ); return( 0 ); } @@ -569,8 +583,8 @@ vips_foreign_load_png_load( VipsForeignLoad *load ) * buffer, then copy to out. */ t[0] = vips_image_new_memory(); - vips_foreign_load_png_set_header( png, t[0] ); - if( vips_image_write_prepare( t[0] ) ) + if( vips_foreign_load_png_set_header( png, t[0] ) || + vips_image_write_prepare( t[0] ) ) return( -1 ); if( (error = spng_decode_image( png->ctx, @@ -591,7 +605,9 @@ vips_foreign_load_png_load( VipsForeignLoad *load ) } else { t[0] = vips_image_new(); - vips_foreign_load_png_set_header( png, t[0] ); + + if( vips_foreign_load_png_set_header( png, t[0] ) ) + return( -1 ); /* We can decode these progressively. */ diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index cce9a112..abbee032 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -548,6 +548,15 @@ png2vips_header( Read *read, VipsImage *out ) &text_ptr, &num_text ) > 0 ) { int i; + /* Very large numbers of text chunks are used in DoS + * attacks. + */ + if( num_text > 10 ) { + vips_error( "vipspng", + "%s", _( "too many text chunks" ) ); + return( -1 ); + } + for( i = 0; i < num_text; i++ ) /* .text is always a null-terminated C string. */