From 5176b4a17ec9ca5151f1b8b503b2f237f3c83b27 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 22 Mar 2018 12:08:39 +0000 Subject: [PATCH] better header sniffing for small files vips__get_bytes() used to fail if the file was too small for the allocated buffer, which was a problem for svg, since files can be extremely small. This change makes vips__get_bytes() return the number of bytes read, so the is_a testers can work on files smaller than the max header size. --- ChangeLog | 1 + libvips/foreign/gifload.c | 2 +- libvips/foreign/jpeg2vips.c | 2 +- libvips/foreign/matlab.c | 2 +- libvips/foreign/openexr2vips.c | 2 +- libvips/foreign/pdfload.c | 2 +- libvips/foreign/ppm.c | 2 +- libvips/foreign/svgload.c | 5 +++-- libvips/foreign/tiff2vips.c | 2 +- libvips/foreign/vipspng.c | 2 +- libvips/foreign/webp2vips.c | 2 +- libvips/include/vips/util.h | 3 ++- libvips/iofuncs/util.c | 27 +++++++++++---------------- libvips/iofuncs/vips.c | 4 ++-- 14 files changed, 28 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7cde3231..2f015aed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ - add vips_sobel() and vips_canny() edge detectors - add vips_rotate() ... a convenience method for vips_similarity() - svgload was missing is_a [lovell] +- better header sniffing for small files 12/3/18 started 8.6.4 - better fitting of fonts with overhanging edges, thanks AdriĆ  diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index c43f9a05..4860a66e 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -383,7 +383,7 @@ vips_foreign_load_gif_is_a( const char *filename ) { unsigned char buf[4]; - if( vips__get_bytes( filename, buf, 4 ) && + if( vips__get_bytes( filename, buf, 4 ) == 4 && vips_foreign_load_gif_is_a_buffer( buf, 4 ) ) return( 1 ); diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 4acd6959..ceed5918 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -968,7 +968,7 @@ vips__isjpeg( const char *filename ) { unsigned char buf[2]; - if( vips__get_bytes( filename, buf, 2 ) && + if( vips__get_bytes( filename, buf, 2 ) == 2 && vips__isjpeg_buffer( buf, 2 ) ) return( 1 ); diff --git a/libvips/foreign/matlab.c b/libvips/foreign/matlab.c index b2d6a01a..5335647b 100644 --- a/libvips/foreign/matlab.c +++ b/libvips/foreign/matlab.c @@ -323,7 +323,7 @@ vips__mat_ismat( const char *filename ) { unsigned char buf[15]; - if( vips__get_bytes( filename, buf, 10 ) && + if( vips__get_bytes( filename, buf, 10 ) == 10 && vips_isprefix( "MATLAB 5.0", (char *) buf ) ) return( 1 ); diff --git a/libvips/foreign/openexr2vips.c b/libvips/foreign/openexr2vips.c index 7d472561..8e113634 100644 --- a/libvips/foreign/openexr2vips.c +++ b/libvips/foreign/openexr2vips.c @@ -107,7 +107,7 @@ vips__openexr_isexr( const char *filename ) { unsigned char buf[4]; - if( vips__get_bytes( filename, buf, 4 ) ) + if( vips__get_bytes( filename, buf, 4 ) == 4 ) if( buf[0] == 0x76 && buf[1] == 0x2f && buf[2] == 0x31 && buf[3] == 0x01 ) return( TRUE ); diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index 289c937d..89f1c960 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -165,7 +165,7 @@ vips_foreign_load_pdf_is_a( const char *filename ) { unsigned char buf[4]; - if( vips__get_bytes( filename, buf, 4 ) && + if( vips__get_bytes( filename, buf, 4 ) == 4 && vips_foreign_load_pdf_is_a_buffer( buf, 4 ) ) return( 1 ); diff --git a/libvips/foreign/ppm.c b/libvips/foreign/ppm.c index 9a7677f5..a5022e78 100644 --- a/libvips/foreign/ppm.c +++ b/libvips/foreign/ppm.c @@ -514,7 +514,7 @@ vips__ppm_isppm( const char *filename ) { VipsPel buf[3]; - if( vips__get_bytes( filename, buf, 2 ) ) { + if( vips__get_bytes( filename, buf, 2 ) == 2 ) { int i; buf[2] = '\0'; diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 279ebc1e..fd4b9776 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -458,9 +458,10 @@ static gboolean vips_foreign_load_svg_file_is_a( const char *filename ) { unsigned char buf[300]; + guint64 bytes; - return( vips__get_bytes( filename, buf, 300 ) && - vips_foreign_load_svg_is_a( buf, 300 ) ); + return( (bytes = vips__get_bytes( filename, buf, 300 )) > 0 && + vips_foreign_load_svg_is_a( buf, bytes ) ); } static int diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index ced03af5..49220307 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -2362,7 +2362,7 @@ vips__istiff( const char *filename ) { unsigned char buf[4]; - if( vips__get_bytes( filename, buf, 4 ) && + if( vips__get_bytes( filename, buf, 4 ) == 4 && vips__istiff_buffer( buf, 4 ) ) return( TRUE ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 65958eb9..b645da3a 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -677,7 +677,7 @@ vips__png_ispng( const char *filename ) { unsigned char buf[8]; - return( vips__get_bytes( filename, buf, 8 ) && + return( vips__get_bytes( filename, buf, 8 ) == 8 && vips__png_ispng_buffer( buf, 8 ) ); } diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 971f9238..b14a61b2 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -119,7 +119,7 @@ vips__iswebp( const char *filename ) */ unsigned char header[12]; - if( vips__get_bytes( filename, header, 12 ) && + if( vips__get_bytes( filename, header, 12 ) == 12 && vips__iswebp_buffer( header, 12 ) ) return( 1 ); diff --git a/libvips/include/vips/util.h b/libvips/include/vips/util.h index aa693183..f481e943 100644 --- a/libvips/include/vips/util.h +++ b/libvips/include/vips/util.h @@ -266,7 +266,8 @@ char *vips__file_read( FILE *fp, const char *name, size_t *length_out ); char *vips__file_read_name( const char *name, const char *fallback_dir, size_t *length_out ); int vips__file_write( void *data, size_t size, size_t nmemb, FILE *stream ); -int vips__get_bytes( const char *filename, unsigned char buf[], int len ); +guint64 vips__get_bytes( const char *filename, + unsigned char buf[], guint64 len ); int vips__fgetc( FILE *fp ); GValue *vips__gvalue_ref_string_new( const char *text ); diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index e22dca85..871a0af9 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -844,33 +844,28 @@ vips__file_write( void *data, size_t size, size_t nmemb, FILE *stream ) return( 0 ); } -/* Read a few bytes from the start of a file. For sniffing file types. - * Filename may contain a mode. +/* Read a few bytes from the start of a file. This is used for sniffing file + * types, so we must read binary. + * + * Return the number of bytes actually read (the file might be shorter than + * len), or 0 for error. */ -int -vips__get_bytes( const char *filename, unsigned char buf[], int len ) +guint64 +vips__get_bytes( const char *filename, unsigned char buf[], guint64 len ) { - char name[FILENAME_MAX]; - char mode[FILENAME_MAX]; int fd; - - /* Split off the mode part. - */ - im_filename_split( filename, name, mode ); + guint64 bytes_read; /* File may not even exist (for tmp images for example!) * so no hasty messages. And the file might be truncated, so no error * on read either. */ - if( (fd = vips__open_read( name )) == -1 ) + if( (fd = vips__open_read( filename )) == -1 ) return( 0 ); - if( read( fd, buf, len ) != len ) { - close( fd ); - return( 0 ); - } + bytes_read = read( fd, buf, len ); close( fd ); - return( 1 ); + return( bytes_read ); } /* We try to support stupid DOS files too. These have \r\n (13, 10) as line diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index 50ed9d58..49e6614f 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -255,9 +255,9 @@ vips__file_magic( const char *filename ) { guint32 magic; - if( vips__get_bytes( filename, (unsigned char *) &magic, 4 ) && + if( vips__get_bytes( filename, (unsigned char *) &magic, 4 ) == 4 && (magic == VIPS_MAGIC_INTEL || - magic == VIPS_MAGIC_SPARC ) ) + magic == VIPS_MAGIC_SPARC) ) return( magic ); return( 0 );