From e8b83aa96e0bdf4ca453f100d92aee2c8e043392 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Apr 2012 13:37:05 +0100 Subject: [PATCH] fail if numeric args to vips are malformed --- libvips/iofuncs/error.c | 6 +++++ libvips/iofuncs/object.c | 45 ++++++++++++++++++++++++++++++++----- libvips/iofuncs/operation.c | 5 ++++- tools/vips.c | 2 +- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index 61fb7013..ceb1854e 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -262,6 +262,12 @@ vips_error_g( GError **error ) if( !vips_domain ) vips_domain = g_quark_from_string( "libvips" ); + /* glib does not expect a trailing '\n' and vips always has one. + */ + g_mutex_lock( vips__global_lock ); + vips_buf_removec( &vips_error_buf, '\n' ); + g_mutex_unlock( vips__global_lock ); + g_set_error( error, vips_domain, -1, "%s", vips_error_buffer() ); vips_error_clear(); } diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 69665d6b..c161b87c 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1477,26 +1477,53 @@ vips_object_set_argument_from_string( VipsObject *object, else if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) ) { gboolean b; - g_value_init( &gvalue, G_TYPE_BOOLEAN ); b = TRUE; if( value && (strcasecmp( value, "false" ) == 0 || strcasecmp( value, "no" ) == 0 || strcmp( value, "0" ) == 0) ) b = FALSE; + + g_value_init( &gvalue, G_TYPE_BOOLEAN ); g_value_set_boolean( &gvalue, b ); } else if( G_IS_PARAM_SPEC_INT( pspec ) ) { + int i; + + if( sscanf( value, "%d", &i ) != 1 ) { + vips_error( class->nickname, + _( "'%s' is not an integer" ), value ); + return( -1 ); + } + g_value_init( &gvalue, G_TYPE_INT ); - g_value_set_int( &gvalue, atoi( value ) ); + g_value_set_int( &gvalue, i ); } else if( G_IS_PARAM_SPEC_UINT64( pspec ) ) { + /* Not allways the same as guint64 :-( argh. + */ + long long l; + + if( sscanf( value, "%Ld", &l ) != 1 ) { + vips_error( class->nickname, + _( "'%s' is not an integer" ), value ); + return( -1 ); + } + g_value_init( &gvalue, G_TYPE_UINT64 ); - g_value_set_uint64( &gvalue, atoll( value ) ); + g_value_set_uint64( &gvalue, l ); } else if( G_IS_PARAM_SPEC_DOUBLE( pspec ) ) { + double d; + + if( sscanf( value, "%lg", &d ) != 1 ) { + vips_error( class->nickname, + _( "'%s' is not a double" ), value ); + return( -1 ); + } + g_value_init( &gvalue, G_TYPE_DOUBLE ); - g_value_set_double( &gvalue, atof( value ) ); + g_value_set_double( &gvalue, d ); } else if( G_IS_PARAM_SPEC_ENUM( pspec ) ) { GEnumValue *enum_value; @@ -1518,8 +1545,16 @@ vips_object_set_argument_from_string( VipsObject *object, else if( G_IS_PARAM_SPEC_FLAGS( pspec ) ) { /* Hard to set from a symbolic name. Just take an int. */ + int i; + + if( sscanf( value, "%d", &i ) != 1 ) { + vips_error( class->nickname, + _( "'%s' is not an integer" ), value ); + return( -1 ); + } + g_value_init( &gvalue, otype ); - g_value_set_flags( &gvalue, atoi( value ) ); + g_value_set_flags( &gvalue, i ); } else { g_value_init( &gvalue, G_TYPE_STRING ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index df7b757b..3422f7bb 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -697,6 +697,7 @@ vips_call_options_set( const gchar *option_name, const gchar *value, vips_call_find_pspec, (void *) name, NULL )) ) { vips_error( VIPS_OBJECT_GET_CLASS( operation )->nickname, _( "unknown argument '%s'" ), name ); + vips_error_g( error ); return( FALSE ); } argument_class = argument_instance->argument_class; @@ -705,8 +706,10 @@ vips_call_options_set( const gchar *option_name, const gchar *value, if( (argument_class->flags & VIPS_ARGUMENT_INPUT) ) { if( vips_object_set_argument_from_string( VIPS_OBJECT( operation ), - g_param_spec_get_name( pspec ), value ) ) + g_param_spec_get_name( pspec ), value ) ) { + vips_error_g( error ); return( FALSE ); + } #ifdef VIPS_DEBUG { diff --git a/tools/vips.c b/tools/vips.c index c0074a1c..63be2fa2 100644 --- a/tools/vips.c +++ b/tools/vips.c @@ -942,7 +942,7 @@ parse_options( GOptionContext *context, int *argc, char **argv ) g_error_free( error ); } - error_exit( "%s", g_get_prgname() ); + error_exit( NULL ); } /* We support --plugin and --version for all cases.