fix out of bounds exif read in heifload

We were subtracting 4 from the length of the exif data block without
checking that there were 4 or more bytes there.
This commit is contained in:
John Cupitt 2020-10-20 08:54:54 +01:00
parent 0131d4d3eb
commit ae82bcc3e8
3 changed files with 14 additions and 3 deletions

View File

@ -1,6 +1,7 @@
18/10/20 started 8.10.3 18/10/20 started 8.10.3
- relax heic is_a rules [hisham] - relax heic is_a rules [hisham]
- fix vips7 webp load [barryspearce] - fix vips7 webp load [barryspearce]
- fix out of bounds exif read in heifload
6/9/20 started 8.10.2 6/9/20 started 8.10.2
- update magicksave/load profile handling [kelilevi] - update magicksave/load profile handling [kelilevi]

View File

@ -158,10 +158,18 @@ show_values( ExifData *data )
* their default value and we won't know about it. * their default value and we won't know about it.
*/ */
static ExifData * static ExifData *
vips_exif_load_data_without_fix( const void *data, int length ) vips_exif_load_data_without_fix( const void *data, size_t length )
{ {
ExifData *ed; ExifData *ed;
/* exif_data_load_data() only allows uint for length. Limit it to less
* than that: 2**20 should be enough for anyone.
*/
if( length > 1 << 20 ) {
vips_error( "exif", "%s", _( "exif too large" ) );
return( NULL );
}
if( !(ed = exif_data_new()) ) { if( !(ed = exif_data_new()) ) {
vips_error( "exif", "%s", _( "unable to init exif" ) ); vips_error( "exif", "%s", _( "unable to init exif" ) );
return( NULL ); return( NULL );

View File

@ -464,7 +464,7 @@ vips_foreign_load_heif_set_header( VipsForeignLoadHeif *heif, VipsImage *out )
char name[256]; char name[256];
#ifdef DEBUG #ifdef DEBUG
printf( "metadata type = %s, length = %zd\n", type, length ); printf( "metadata type = %s, length = %zu\n", type, length );
#endif /*DEBUG*/ #endif /*DEBUG*/
if( !(data = VIPS_ARRAY( out, length, unsigned char )) ) if( !(data = VIPS_ARRAY( out, length, unsigned char )) )
@ -479,7 +479,8 @@ vips_foreign_load_heif_set_header( VipsForeignLoadHeif *heif, VipsImage *out )
/* We need to skip the first four bytes of EXIF, they just /* We need to skip the first four bytes of EXIF, they just
* contain the offset. * contain the offset.
*/ */
if( g_ascii_strcasecmp( type, "exif" ) == 0 ) { if( length > 4 &&
g_ascii_strcasecmp( type, "exif" ) == 0 ) {
data += 4; data += 4;
length -= 4; length -= 4;
} }
@ -492,6 +493,7 @@ vips_foreign_load_heif_set_header( VipsForeignLoadHeif *heif, VipsImage *out )
if( g_ascii_strcasecmp( type, "exif" ) == 0 ) if( g_ascii_strcasecmp( type, "exif" ) == 0 )
vips_snprintf( name, 256, VIPS_META_EXIF_NAME ); vips_snprintf( name, 256, VIPS_META_EXIF_NAME );
else if( g_ascii_strcasecmp( type, "mime" ) == 0 && else if( g_ascii_strcasecmp( type, "mime" ) == 0 &&
length > 10 &&
vips_isprefix( "<x:xmpmeta", (const char *) data ) ) vips_isprefix( "<x:xmpmeta", (const char *) data ) )
vips_snprintf( name, 256, VIPS_META_XMP_NAME ); vips_snprintf( name, 256, VIPS_META_XMP_NAME );
else else