From 1f5ff2e6a585d0b5dca501945fabfeb48b1bf547 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 23 Apr 2023 12:10:21 +1200 Subject: Allow using snprintf() instead of sprintf() in wrappers We aim to produce code that works with C90 or C++98 so we can't assume snprintf() is available, but it almost always is (even on systems from before it was standardised) so having a way to use it is helpful. Enable this automatically if the compiler claims conformance with at least C90 or C++98 and check SWIG_HAVE_SNPRINTF to allow turning on manually, but disable if SWIG_NO_SNPRINTF if defined. The fallback is to call sprintf() without a buffer size check - checking after the call is really shutting the stable door after the horse has bolted, and most of our uses either have a fixed maximum possible size or dynamically allocate a buffer that's large enough. Fixes: #2502 (sprintf deprecation warnings on macos) Fixes: #2548 --- Lib/csharp/csharp.swg | 2 +- Lib/d/dexception.swg | 2 +- Lib/java/java.swg | 2 +- Lib/javascript/jsc/javascripthelpers.swg | 2 +- Lib/javascript/v8/javascripthelpers.swg | 2 +- Lib/mzscheme/mzrun.swg | 11 ++++++----- Lib/ocaml/cstring.i | 10 +++++----- Lib/ocaml/typecheck.i | 2 +- Lib/octave/octcontainer.swg | 2 +- Lib/perl5/perlprimtypes.swg | 4 ++-- Lib/perl5/typemaps.i | 4 ++-- Lib/ruby/rubycontainer.swg | 2 +- Lib/ruby/rubyerrors.swg | 2 +- Lib/ruby/rubyrun.swg | 10 ++++++---- Lib/scilab/sciarray.swg | 4 ++-- Lib/scilab/sciexception.swg | 9 +++++---- Lib/swig.swg | 20 ++++++++++++++++++++ Lib/tcl/tclprimtypes.swg | 6 +++--- Lib/tcl/tclrun.swg | 2 +- Lib/tcl/typemaps.i | 4 ++-- Lib/typemaps/cstrings.swg | 10 +++++----- 21 files changed, 68 insertions(+), 44 deletions(-) (limited to 'Lib') diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 1f80d12a1..4c04e50c6 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -579,7 +579,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { unsigned long, unsigned short %{ char error_msg[256]; - sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1); SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, error_msg); return $null; %} diff --git a/Lib/d/dexception.swg b/Lib/d/dexception.swg index 1aadbaada..74e0422b1 100644 --- a/Lib/d/dexception.swg +++ b/Lib/d/dexception.swg @@ -15,7 +15,7 @@ unsigned long, unsigned short %{ char error_msg[256]; - sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1); SWIG_DSetPendingException(SWIG_DException, error_msg); return $null; %} diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 8719818bb..1c1a56e69 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1039,7 +1039,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } unsigned long, unsigned short %{ char error_msg[256]; - sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, error_msg); return $null; %} diff --git a/Lib/javascript/jsc/javascripthelpers.swg b/Lib/javascript/jsc/javascripthelpers.swg index 45765433e..bdd5142a5 100644 --- a/Lib/javascript/jsc/javascripthelpers.swg +++ b/Lib/javascript/jsc/javascripthelpers.swg @@ -46,7 +46,7 @@ SWIGINTERN bool JS_veto_set_variable(JSContextRef context, JSObjectRef thisObjec int res; JSStringGetUTF8CString(propertyName, buffer, 256); - res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); + res = SWIG_snprintf(msg, sizeof(msg), "Tried to write read-only variable: %s.", buffer); if(res<0) { SWIG_exception(SWIG_ERROR, "Tried to write read-only variable."); diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg index ea303fa3d..7f7040613 100644 --- a/Lib/javascript/v8/javascripthelpers.swg +++ b/Lib/javascript/v8/javascripthelpers.swg @@ -70,7 +70,7 @@ SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local sproperty; if (property->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocal(&sproperty)) { SWIGV8_WRITE_UTF8(sproperty, buffer, 256); - res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); + res = SWIG_snprintf(msg, sizeof(msg), "Tried to write read-only variable: %s.", buffer); } else { res = -1; diff --git a/Lib/mzscheme/mzrun.swg b/Lib/mzscheme/mzrun.swg index 57d040812..60f5643e2 100644 --- a/Lib/mzscheme/mzrun.swg +++ b/Lib/mzscheme/mzrun.swg @@ -25,9 +25,10 @@ extern "C" { #define SWIG_contract_assert(expr,msg) \ do { \ if (!(expr)) { \ - char *m=(char *) scheme_malloc(strlen(msg)+1000); \ - sprintf(m,"SWIG contract, assertion failed: function=%s, message=%s", \ - (char *) FUNC_NAME,(char *) msg); \ + size_t len=strlen(msg)+1000; \ + char *m=(char *) scheme_malloc(len); \ + SWIG_snprintf2(m, len, "SWIG contract, assertion failed: function=%s, message=%s", \ + (char *) FUNC_NAME,(char *) msg); \ scheme_signal_error(m); \ } \ } while (0) @@ -420,10 +421,10 @@ SWIG_MzScheme_new_scheme_struct (Scheme_Env* env, const char* basename, int L=strlen(mz_dynload_libpaths[k])+strlen("\\")+strlen(mz_dlopen_libraries[i])+1; libp=(char *) malloc(L*sizeof(char)); #ifdef __OS_WIN32 - sprintf(libp,"%s\\%s",mz_dynload_libpaths[k],mz_dlopen_libraries[i]); + SWIG_snprintf2(libp,L,"%s\\%s",mz_dynload_libpaths[k],mz_dlopen_libraries[i]); mz_libraries[i]=(void *) LoadLibrary(libp); #else - sprintf(libp,"%s/%s",mz_dynload_libpaths[k],mz_dlopen_libraries[i]); + SWIG_snprintf2(libp,L,"%s/%s",mz_dynload_libpaths[k],mz_dlopen_libraries[i]); mz_libraries[i]=(void *) dlopen(libp,RTLD_LAZY); #endif if (mz_dynload_debug) { diff --git a/Lib/ocaml/cstring.i b/Lib/ocaml/cstring.i index f1190ad5c..8b72be9d0 100644 --- a/Lib/ocaml/cstring.i +++ b/Lib/ocaml/cstring.i @@ -25,7 +25,7 @@ * * %cstring_bounded_output(char *outx, 512); * void foo(char *outx) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } * */ @@ -144,7 +144,7 @@ * * %cstring_output_maxsize(char *outx, int max) { * void foo(char *outx, int max) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } */ @@ -175,7 +175,7 @@ * * %cstring_output_maxsize(char *outx, int *max) { * void foo(char *outx, int *max) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * *max = strlen(outx); * } */ @@ -213,7 +213,7 @@ * %cstring_output_allocated(char **outx, free($1)); * void foo(char **outx) { * *outx = (char *) malloc(512); - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } */ @@ -241,7 +241,7 @@ * %cstring_output_allocated(char **outx, int *sz, free($1)); * void foo(char **outx, int *sz) { * *outx = (char *) malloc(512); - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * *sz = strlen(outx); * } */ diff --git a/Lib/ocaml/typecheck.i b/Lib/ocaml/typecheck.i index 0c0a600a0..238f90d8d 100644 --- a/Lib/ocaml/typecheck.i +++ b/Lib/ocaml/typecheck.i @@ -183,7 +183,7 @@ unsigned long, unsigned short { char error_msg[256]; - sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1); SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, error_msg); } diff --git a/Lib/octave/octcontainer.swg b/Lib/octave/octcontainer.swg index 394c90bac..5031e703f 100644 --- a/Lib/octave/octcontainer.swg +++ b/Lib/octave/octcontainer.swg @@ -198,7 +198,7 @@ namespace swig return swig::as(item); } catch (const std::exception& e) { char msg[1024]; - sprintf(msg, "in sequence element %d ", _index); + SWIG_snprintf(msg, sizeof(msg), "in sequence element %d ", _index); if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } diff --git a/Lib/perl5/perlprimtypes.swg b/Lib/perl5/perlprimtypes.swg index 4cb675671..d3bec4bd4 100644 --- a/Lib/perl5/perlprimtypes.swg +++ b/Lib/perl5/perlprimtypes.swg @@ -179,7 +179,7 @@ SWIG_From_dec(long long)(long long value) else { //sv = newSVpvf("%lld", value); doesn't work in non 64bit Perl char temp[256]; - sprintf(temp, "%lld", value); + SWIG_snprintf(temp, sizeof(temp), "%lld", value); sv = newSVpv(temp, 0); } return sv_2mortal(sv); @@ -259,7 +259,7 @@ SWIG_From_dec(unsigned long long)(unsigned long long value) else { //sv = newSVpvf("%llu", value); doesn't work in non 64bit Perl char temp[256]; - sprintf(temp, "%llu", value); + SWIG_snprintf(temp, sizeof(temp), "%llu", value); sv = newSVpv(temp, 0); } return sv_2mortal(sv); diff --git a/Lib/perl5/typemaps.i b/Lib/perl5/typemaps.i index 3e1f60d90..078f24ce8 100644 --- a/Lib/perl5/typemaps.i +++ b/Lib/perl5/typemaps.i @@ -206,7 +206,7 @@ output values. if (argvi >= items) { EXTEND(sp, argvi+1); } - sprintf(temp,"%lld", (long long)*($1)); + SWIG_snprintf(temp, sizeof(temp),"%lld", (long long)*($1)); $result = sv_newmortal(); sv_setpv($result,temp); argvi++; @@ -217,7 +217,7 @@ output values. if (argvi >= items) { EXTEND(sp, argvi+1); } - sprintf(temp,"%llu", (unsigned long long)*($1)); + SWIG_snprintf(temp, sizeof(temp),"%llu", (unsigned long long)*($1)); $result = sv_newmortal(); sv_setpv($result,temp); argvi++; diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index 597ae83d2..ab2eeae83 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -186,7 +186,7 @@ namespace swig return swig::as(item); } catch (const std::invalid_argument& e) { char msg[1024]; - sprintf(msg, "in sequence element %d ", _index); + SWIG_snprintf(msg, sizeof(msg), "in sequence element %d ", _index); VALUE lastErr = rb_gv_get("$!"); if ( lastErr == Qnil ) { %type_error(swig::type_name()); diff --git a/Lib/ruby/rubyerrors.swg b/Lib/ruby/rubyerrors.swg index 434544bc9..ad71d1d39 100644 --- a/Lib/ruby/rubyerrors.swg +++ b/Lib/ruby/rubyerrors.swg @@ -110,7 +110,7 @@ const char* Ruby_Format_TypeError( const char* msg, } str = rb_str_cat2( str, "Expected argument " ); - sprintf( buf, "%d of type ", argn-1 ); + SWIG_snprintf( buf, sizeof( buf), "%d of type ", argn-1 ); str = rb_str_cat2( str, buf ); str = rb_str_cat2( str, type ); str = rb_str_cat2( str, ", but got " ); diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 885292481..456bd9d8f 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -151,8 +151,9 @@ SWIG_Ruby_InitRuntime(void) SWIGRUNTIME void SWIG_Ruby_define_class(swig_type_info *type) { - char *klass_name = (char *) malloc(4 + strlen(type->name) + 1); - sprintf(klass_name, "TYPE%s", type->name); + size_t klass_len = 4 + strlen(type->name) + 1; + char *klass_name = (char *) malloc(klass_len); + SWIG_snprintf(klass_name, klass_len, "TYPE%s", type->name); if (NIL_P(_cSWIG_Pointer)) { _cSWIG_Pointer = rb_define_class_under(_mSWIG, "Pointer", rb_cObject); rb_undef_method(CLASS_OF(_cSWIG_Pointer), "new"); @@ -208,8 +209,9 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) SWIG_RubyAddTracking(ptr, obj); } } else { - klass_name = (char *) malloc(4 + strlen(type->name) + 1); - sprintf(klass_name, "TYPE%s", type->name); + size_t klass_len = 4 + strlen(type->name) + 1; + klass_name = (char *) malloc(klass_len); + SWIG_snprintf(klass_name, klass_len, "TYPE%s", type->name); klass = rb_const_get(_mSWIG, rb_intern(klass_name)); free((void *) klass_name); obj = Data_Wrap_Struct(klass, 0, 0, ptr); diff --git a/Lib/scilab/sciarray.swg b/Lib/scilab/sciarray.swg index c00e3837e..97b30a29e 100644 --- a/Lib/scilab/sciarray.swg +++ b/Lib/scilab/sciarray.swg @@ -40,8 +40,8 @@ } else { char errmsg[100]; - sprintf(errmsg, "Size of input data (%d) is too big (maximum is %d)", - iRows*iCols, $1_dim0); + SWIG_snprintf2(errmsg, sizeof(errmsg), "Size of input data (%d) is too big (maximum is %d)", + iRows*iCols, $1_dim0); SWIG_exception_fail(SWIG_OverflowError, errmsg); } } diff --git a/Lib/scilab/sciexception.swg b/Lib/scilab/sciexception.swg index 1d653b314..9b842cf2f 100644 --- a/Lib/scilab/sciexception.swg +++ b/Lib/scilab/sciexception.swg @@ -17,20 +17,20 @@ size_t, size_t&, ptrdiff_t, ptrdiff_t& { char obj[20]; - sprintf(obj, "%d", (int)$1); + SWIG_snprintf(obj, sizeof(obj), "%d", (int)$1); SWIG_Scilab_Raise_Ex(obj, "$type", $descriptor); } %typemap(throws, noblock=1) enum SWIGTYPE { char obj[20]; - sprintf(obj, "%d", (int)$1); + SWIG_snprintf(obj, sizeof(obj), "%d", (int)$1); SWIG_Scilab_Raise_Ex(obj, "$type", $descriptor); } %typemap(throws, noblock=1) float, double, float&, double& { char obj[20]; - sprintf(obj, "%5.3f", (double)$1); + SWIG_snprintf(obj, sizeof(obj), "%5.3f", (double)$1); SWIG_Scilab_Raise_Ex(obj, "$type", $descriptor); } @@ -44,7 +44,8 @@ %typemap(throws, noblock=1) char, char& { char obj[2]; - sprintf(obj, "%c", (char)$1); + obj[0] = (char)$1; + obj[1] = 0; SWIG_Scilab_Raise_Ex(obj, "$type", $descriptor); } diff --git a/Lib/swig.swg b/Lib/swig.swg index 9f9d53349..f904f53c6 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -727,3 +727,23 @@ template T SwigValueInit() { %} #endif +%insert("runtime") %{ +/* C99 and C++11 should provide snprintf, but define SWIG_NO_SNPRINTF + * if you're missing it. + */ +#if ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || \ + (defined __cplusplus && __cplusplus >= 201103L) || \ + defined SWIG_HAVE_SNPRINTF) && \ + !defined SWIG_NO_SNPRINTF +# define SWIG_snprintf(O,S,F,A) snprintf(O,S,F,A) +# define SWIG_snprintf2(O,S,F,A,B) snprintf(O,S,F,A,B) +#else +/* Fallback versions ignore the buffer size, but most of our uses either have a + * fixed maximum possible size or dynamically allocate a buffer that's large + * enough. + */ +# define SWIG_snprintf(O,S,F,A) sprintf(O,F,A) +# define SWIG_snprintf2(O,S,F,A,B) sprintf(O,F,A,B) +#endif + +%} diff --git a/Lib/tcl/tclprimtypes.swg b/Lib/tcl/tclprimtypes.swg index febbffb73..06cc52774 100644 --- a/Lib/tcl/tclprimtypes.swg +++ b/Lib/tcl/tclprimtypes.swg @@ -61,7 +61,7 @@ SWIG_From_dec(unsigned long)(unsigned long value) return SWIG_From(long)(%numeric_cast(value, long)); } else { char temp[256]; - sprintf(temp, "%lu", value); + SWIG_snprintf(temp, sizeof(temp), "%lu", value); return Tcl_NewStringObj(temp,-1); } } @@ -122,7 +122,7 @@ SWIG_From_dec(long long)(long long value) return SWIG_From(long)(%numeric_cast(value,long)); } else { char temp[256]; - sprintf(temp, "%lld", value); + SWIG_snprintf(temp, sizeof(temp), "%lld", value); return Tcl_NewStringObj(temp,-1); } } @@ -163,7 +163,7 @@ SWIG_From_dec(unsigned long long)(unsigned long long value) return SWIG_From(long long)(%numeric_cast(value, long long)); } else { char temp[256]; - sprintf(temp, "%llu", value); + SWIG_snprintf(temp, sizeof(temp), "%llu", value); return Tcl_NewStringObj(temp,-1); } } diff --git a/Lib/tcl/tclrun.swg b/Lib/tcl/tclrun.swg index e8136051f..df4cbaef1 100644 --- a/Lib/tcl/tclrun.swg +++ b/Lib/tcl/tclrun.swg @@ -707,7 +707,7 @@ SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char argerror: { char temp[32]; - sprintf(temp,"%d", argno+1); + SWIG_snprintf(temp, sizeof(temp), "%d", argno+1); c = strchr(fmt,':'); if (!c) c = strchr(fmt,';'); if (!c) c = (char *)""; diff --git a/Lib/tcl/typemaps.i b/Lib/tcl/typemaps.i index 04a5c78f3..613be95a3 100644 --- a/Lib/tcl/typemaps.i +++ b/Lib/tcl/typemaps.i @@ -275,7 +275,7 @@ output values. { char temp[256]; Tcl_Obj *o; - sprintf(temp,"%lld",(long long)*($1)); + SWIG_snprintf(temp,sizeof(temp),"%lld",(long long)*($1)); o = Tcl_NewStringObj(temp,-1); Tcl_ListObjAppendElement(interp,Tcl_GetObjResult(interp),o); } @@ -284,7 +284,7 @@ output values. { char temp[256]; Tcl_Obj *o; - sprintf(temp,"%llu",(unsigned long long)*($1)); + SWIG_snprintf(temp,sizeof(temp),"%llu",(unsigned long long)*($1)); o = Tcl_NewStringObj(temp,-1); Tcl_ListObjAppendElement(interp,Tcl_GetObjResult(interp),o); } diff --git a/Lib/typemaps/cstrings.swg b/Lib/typemaps/cstrings.swg index 42ce4d9bb..7a7e2c1f9 100644 --- a/Lib/typemaps/cstrings.swg +++ b/Lib/typemaps/cstrings.swg @@ -50,7 +50,7 @@ * * %cstring_bounded_output(Char *outx, 512); * void foo(Char *outx) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } * */ @@ -175,7 +175,7 @@ * * %cstring_output_maxsize(Char *outx, int max) { * void foo(Char *outx, int max) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } */ @@ -205,7 +205,7 @@ * * %cstring_output_withsize(Char *outx, int *max) { * void foo(Char *outx, int *max) { - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * *max = strlen(outx); * } */ @@ -239,7 +239,7 @@ * %cstring_output_allocate(Char **outx, free($1)); * void foo(Char **outx) { * *outx = (Char *) malloc(512); - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * } */ @@ -266,7 +266,7 @@ * %cstring_output_allocate_size(Char **outx, int *sz, free($1)); * void foo(Char **outx, int *sz) { * *outx = (Char *) malloc(512); - * sprintf(outx,"blah blah\n"); + * strcpy(outx,"blah blah\n"); * *sz = strlen(outx); * } */ -- cgit v1.2.1