From 0e7f2124c73988a1cdb1e227d35c0e4e775b6517 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 1 Jan 2021 11:12:15 +0000 Subject: [PATCH] improve file testing and add some checks that the load subclasses have been defined correctly --- libvips/foreign/foreign.c | 65 +++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index fb4df9c8..8ce247af 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -381,10 +381,13 @@ vips_foreign_init( VipsForeign *object ) static void * file_add_class( VipsForeignClass *class, GSList **files ) { - /* Append so we don't reverse the list of files. Sort will not reorder - * items of equal priority. + /* We exclude "rawload" as it has a different API. */ - *files = g_slist_append( *files, class ); + if( !vips_isprefix( "rawload", VIPS_OBJECT_CLASS( class )->nickname ) ) + /* Append so we don't reverse the list of files. Sort will + * not reorder items of equal priority. + */ + *files = g_slist_append( *files, class ); return( NULL ); } @@ -437,6 +440,7 @@ vips_foreign_map( const char *base, VipsSListMap2Fn fn, void *a, void *b ) } #endif /*DEBUG*/ result = vips_slist_map2( files, fn, a, b ); + g_slist_free( files ); return( result ); @@ -496,14 +500,21 @@ vips_foreign_find_load_sub( VipsForeignLoadClass *load_class, VipsObjectClass *object_class = VIPS_OBJECT_CLASS( load_class ); VipsForeignClass *class = VIPS_FOREIGN_CLASS( load_class ); + /* Ignore the buffer and source loaders. + */ + if( vips_ispostfix( object_class->nickname, "_buffer" ) || + vips_ispostfix( object_class->nickname, "_source" ) ) + return( NULL ); + #ifdef DEBUG printf( "vips_foreign_find_load_sub: %s\n", VIPS_OBJECT_CLASS( class )->nickname ); #endif /*DEBUG*/ - if( load_class->is_a && - !vips_ispostfix( object_class->nickname, "_buffer" ) && - !vips_ispostfix( object_class->nickname, "_source" ) ) { + /* Try to sniff the filetype from the first few bytes, if we can, + * otherwise fall back to checking the filename suffix. + */ + if( load_class->is_a ) { if( load_class->is_a( filename ) ) return( load_class ); @@ -511,14 +522,13 @@ vips_foreign_find_load_sub( VipsForeignLoadClass *load_class, printf( "vips_foreign_find_load_sub: is_a failed\n" ); #endif /*DEBUG*/ } - else if( class->suffs && - vips_filename_suffix_match( filename, class->suffs ) ) - return( load_class ); - else { -#ifdef DEBUG - printf( "vips_foreign_find_load_sub: suffix match failed\n" ); -#endif /*DEBUG*/ + else if( class->suffs ) { + if( vips_filename_suffix_match( filename, class->suffs ) ) + return( load_class ); } + else + g_warning( "loader %s has no is_a method and no suffix list", + object_class->nickname ); return( NULL ); } @@ -606,10 +616,18 @@ vips_foreign_find_load_buffer_sub( VipsForeignLoadClass *load_class, { VipsObjectClass *object_class = VIPS_OBJECT_CLASS( load_class ); - if( load_class->is_a_buffer && - vips_ispostfix( object_class->nickname, "_buffer" ) && - load_class->is_a_buffer( *buf, *len ) ) - return( load_class ); + /* Skip non-buffer loaders. + */ + if( !vips_ispostfix( object_class->nickname, "_buffer" ) ) + return( NULL ); + + if( load_class->is_a_buffer ) { + if( load_class->is_a_buffer( *buf, *len ) ) + return( load_class ); + } + else + g_warning( "loader %s has no is_a_buffer method", + object_class->nickname ); return( NULL ); } @@ -656,9 +674,13 @@ vips_foreign_find_load_source_sub( void *item, void *a, void *b ) VipsForeignLoadClass *load_class = VIPS_FOREIGN_LOAD_CLASS( item ); VipsSource *source = VIPS_SOURCE( a ); - if( load_class->is_a_source && - vips_ispostfix( object_class->nickname, "_source" ) ) { - /* We may have done a read() rather than a sniff() in one of + /* Skip non-source loaders. + */ + if( !vips_ispostfix( object_class->nickname, "_source" ) ) + return( NULL ); + + if( load_class->is_a_source ) { + /* We may have done a _read() rather than a _sniff() in one of * the is_a testers. Always rewind. */ (void) vips_source_rewind( source ); @@ -666,6 +688,9 @@ vips_foreign_find_load_source_sub( void *item, void *a, void *b ) if( load_class->is_a_source( source ) ) return( load_class ); } + else + g_warning( "loader %s has no is_a_source method", + object_class->nickname ); return( NULL ); }