From d918bddfc09c8f59fa45b1772cba106b663003b3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Nov 2012 00:45:18 +0000 Subject: [PATCH] Fix segfaults when using filename paths greater than 1024 characters in length - use String * and heap instead of fixed size static char array buffers. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13904 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 6 +++- Source/Modules/csharp.cxx | 7 +++-- Source/Modules/d.cxx | 7 +++-- Source/Modules/go.cxx | 4 ++- Source/Modules/java.cxx | 7 +++-- Source/Modules/main.cxx | 41 +++++++++++++++----------- Source/Modules/php.cxx | 4 ++- Source/Modules/python.cxx | 7 +++-- Source/Modules/ruby.cxx | 7 +++-- Source/Preprocessor/cpp.c | 20 +++++++++---- Source/Swig/include.c | 60 ++++++++++++++------------------------- Source/Swig/swigfile.h | 8 +++--- 12 files changed, 100 insertions(+), 78 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 2932b5003..39da2bb4f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,7 +5,11 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.9 (in progress) =========================== -2012-11-14: [ccache-swig] Apply patch #3586392 from Frederik Deweerdt to fix some error cases - incorrectly using +2012-11-17: wsfulton + Fix segfaults when using filename paths greater than 1024 characters in length. + +2012-11-14: wsfulton + [ccache-swig] Apply patch #3586392 from Frederik Deweerdt to fix some error cases - incorrectly using memory after it has been deleted. 2012-11-09: vzeitlin diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index b8133b74a..9f902b76d 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -405,8 +405,11 @@ public: Printf(f_directors, "/* ---------------------------------------------------\n"); Printf(f_directors, " * C++ director class methods\n"); Printf(f_directors, " * --------------------------------------------------- */\n\n"); - if (outfile_h) - Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + if (outfile_h) { + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "#include \"%s\"\n\n", filename); + Delete(filename); + } } Printf(f_runtime, "\n"); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 4f110fb8d..503f90069 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -490,8 +490,11 @@ public: Printf(f_directors, "/* ---------------------------------------------------\n"); Printf(f_directors, " * C++ director class methods\n"); Printf(f_directors, " * --------------------------------------------------- */\n\n"); - if (outfile_h) - Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + if (outfile_h) { + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "#include \"%s\"\n\n", filename); + Delete(filename); + } } Printf(f_runtime, "\n"); diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 7c34f8b9a..347cf33a4 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -371,7 +371,9 @@ private: Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module); Printf(f_c_directors, "\n// C++ director class methods.\n"); - Printf(f_c_directors, "#include \"%s\"\n\n", Swig_file_filename(c_filename_h)); + String *filename = Swig_file_filename(c_filename_h); + Printf(f_c_directors, "#include \"%s\"\n\n", filename); + Delete(filename); } Swig_banner(f_go_begin); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 1ee7a97e3..14cfeaf20 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -417,8 +417,11 @@ public: Printf(f_directors, "/* ---------------------------------------------------\n"); Printf(f_directors, " * C++ director class methods\n"); Printf(f_directors, " * --------------------------------------------------- */\n\n"); - if (outfile_h) - Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + if (outfile_h) { + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "#include \"%s\"\n\n", filename); + Delete(filename); + } } Printf(f_runtime, "\n"); diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 8e2b428f4..d2876c16f 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -199,22 +199,24 @@ static List *libfiles = 0; static List *all_output_files = 0; /* ----------------------------------------------------------------------------- - * check_suffix() + * check_extension() * - * Checks the suffix of a file to see if we should emit extern declarations. + * Checks the extension of a file to see if we should emit extern declarations. * ----------------------------------------------------------------------------- */ -static int check_suffix(String *filename) { +static bool check_extension(String *filename) { + bool wanted = false; const char *name = Char(filename); - const char *c; if (!name) return 0; - c = Swig_file_suffix(name); + String *extension = Swig_file_extension(name); + const char *c = Char(extension); if ((strcmp(c, ".c") == 0) || (strcmp(c, ".C") == 0) || (strcmp(c, ".cc") == 0) || (strcmp(c, ".cxx") == 0) || (strcmp(c, ".c++") == 0) || (strcmp(c, ".cpp") == 0)) { - return 1; + wanted = true; } - return 0; + Delete(extension); + return wanted; } /* ----------------------------------------------------------------------------- @@ -283,15 +285,16 @@ static unsigned int decode_numbers_list(String *numlist) { } /* ----------------------------------------------------------------------------- - * Sets the output directory for language specific (proxy) files if not set and - * corrects the directory name and adds trailing file separator if necessary. + * Sets the output directory for language specific (proxy) files from the + * C wrapper file if not set and corrects the directory name and adds a trailing + * file separator if necessary. * ----------------------------------------------------------------------------- */ -static void configure_outdir(const String *c_wrapper_file_dir) { +static void configure_outdir(const String *c_wrapper_outfile) { // Use the C wrapper file's directory if the output directory has not been set by user if (!outdir || Len(outdir) == 0) - outdir = NewString(c_wrapper_file_dir); + outdir = Swig_file_dirname(c_wrapper_outfile); Swig_filename_correct(outdir); @@ -1068,7 +1071,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { String *outfile; File *f_dependencies_file = 0; - char *basename = Swig_file_basename(outcurrentdir ? Swig_file_filename(input_file): Char(input_file)); + String *inputfile_filename = outcurrentdir ? Swig_file_filename(input_file): Copy(input_file); + String *basename = Swig_file_basename(inputfile_filename); if (!outfile_name) { if (CPlusPlus || lang->cplus_runtime_mode()) { outfile = NewStringf("%s_wrap.%s", basename, cpp_extension); @@ -1113,6 +1117,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { Delete(f_dependencies_file); if (depend_only) SWIG_exit(EXIT_SUCCESS); + Delete(inputfile_filename); + Delete(basename); } else { Printf(stderr, "Cannot generate dependencies with -nopreprocess\n"); // Actually we could but it would be inefficient when just generating dependencies, as it would be done after Swig_cparse @@ -1220,7 +1226,8 @@ int SWIG_main(int argc, char *argv[], Language *l) { Setattr(top, "infile", infile); // Note: if nopreprocess then infile is the original input file, otherwise input_file Setattr(top, "inputfile", input_file); - char *basename = Swig_file_basename(outcurrentdir ? Swig_file_filename(infile): Char(infile)); + String *infile_filename = outcurrentdir ? Swig_file_filename(infile): Copy(infile); + String *basename = Swig_file_basename(infile_filename); if (!outfile_name) { if (CPlusPlus || lang->cplus_runtime_mode()) { Setattr(top, "outfile", NewStringf("%s_wrap.%s", basename, cpp_extension)); @@ -1235,19 +1242,21 @@ int SWIG_main(int argc, char *argv[], Language *l) { } else { Setattr(top, "outfile_h", outfile_name_h); } - configure_outdir(Swig_file_dirname(Getattr(top, "outfile"))); + configure_outdir(Getattr(top, "outfile")); if (Swig_contract_mode_get()) { Swig_contracts(top); } - // Check the suffix for a c/c++ file. If so, we're going to declare everything we see as "extern" - ForceExtern = check_suffix(input_file); + // Check the extension for a c/c++ file. If so, we're going to declare everything we see as "extern" + ForceExtern = check_extension(input_file); lang->top(top); if (browse) { Swig_browser(top, 0); } + Delete(infile_filename); + Delete(basename); } } if (dump_lang_symbols) { diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index ab0d0e6b3..1f2078a1e 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -354,7 +354,9 @@ public: Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module); Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module); - Printf(f_directors, "\n#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "\n#include \"%s\"\n\n", filename); + Delete(filename); } /* PHP module file */ diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9d1b3a772..dcf6699b1 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -763,8 +763,11 @@ public: Printf(f_directors, "/* ---------------------------------------------------\n"); Printf(f_directors, " * C++ director class methods\n"); Printf(f_directors, " * --------------------------------------------------- */\n\n"); - if (outfile_h) - Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + if (outfile_h) { + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "#include \"%s\"\n\n", filename); + Delete(filename); + } } /* If shadow classing is enabled, we're going to change the module name to "_module" */ diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 053143899..e31d3b72c 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1142,8 +1142,11 @@ public: Printf(f_directors, "/* ---------------------------------------------------\n"); Printf(f_directors, " * C++ director class methods\n"); Printf(f_directors, " * --------------------------------------------------- */\n\n"); - if (outfile_h) - Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); + if (outfile_h) { + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "#include \"%s\"\n\n", filename); + Delete(filename); + } Delete(module_macro); } diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index b6426f5ab..4366a8434 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -1706,7 +1706,7 @@ String *Preprocessor_parse(String *s) { } else if (Equal(id, kpp_include)) { if (((include_all) || (import_all)) && (allow)) { String *s1, *s2, *fn; - char *dirname; + String *dirname; int sysfile = 0; if (include_all && import_all) { Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall.\n"); @@ -1725,10 +1725,13 @@ String *Preprocessor_parse(String *s) { /* See if the filename has a directory component */ dirname = Swig_file_dirname(Swig_last_file()); - if (sysfile || !strlen(dirname)) + if (sysfile || !Len(dirname)) { + Delete(dirname); dirname = 0; + } if (dirname) { - dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */ + int len = Len(dirname); + Delslice(dirname, len - 1, len); /* Kill trailing directory delimiter */ Swig_push_directory(dirname); } s2 = Preprocessor_parse(s1); @@ -1741,6 +1744,7 @@ String *Preprocessor_parse(String *s) { pop_imported(); } Delete(s2); + Delete(dirname); Delete(s1); } Delete(fn); @@ -1858,7 +1862,7 @@ String *Preprocessor_parse(String *s) { fn = get_filename(s, &sysfile); s1 = cpp_include(fn, sysfile); if (s1) { - char *dirname; + String *dirname; copy_location(s, chunk); add_chunk(ns, chunk, allow); Printf(ns, "%sfile%s%s%s\"%s\" %%beginfile\n", decl, options_whitespace, opt, filename_whitespace, Swig_filename_escape(Swig_last_file())); @@ -1866,10 +1870,13 @@ String *Preprocessor_parse(String *s) { push_imported(); } dirname = Swig_file_dirname(Swig_last_file()); - if (sysfile || !strlen(dirname)) + if (sysfile || !strlen(dirname)) { + Delete(dirname); dirname = 0; + } if (dirname) { - dirname[strlen(dirname) - 1] = 0; /* Kill trailing directory delimiter */ + int len = Len(dirname); + Delslice(dirname, len - 1, len); /* Kill trailing directory delimiter */ Swig_push_directory(dirname); } s2 = Preprocessor_parse(s1); @@ -1882,6 +1889,7 @@ String *Preprocessor_parse(String *s) { addline(ns, s2, allow); Append(ns, "%endoffile"); Delete(s2); + Delete(dirname); Delete(s1); } Delete(fn); diff --git a/Source/Swig/include.c b/Source/Swig/include.c index 3766894ae..6e76f86ba 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -317,58 +317,49 @@ File *Swig_filebyname(const_String_or_char_ptr filename) { } /* ----------------------------------------------------------------------------- - * Swig_file_suffix() + * Swig_file_extension() * - * Returns the suffix of a file + * Returns the extension of a file * ----------------------------------------------------------------------------- */ -char *Swig_file_suffix(const_String_or_char_ptr filename) { - char *d; - char *c = Char(filename); +String *Swig_file_extension(const_String_or_char_ptr filename) { + const char *d; + const char *c = Char(filename); int len = Len(filename); if (strlen(c)) { d = c + len - 1; while (d != c) { if (*d == '.') - return d; + return NewString(d); d--; } - return c + len; + return NewString(c + len); } - return c; + return NewString(c); } /* ----------------------------------------------------------------------------- * Swig_file_basename() * - * Returns the filename with no suffix attached. + * Returns the filename with the extension removed. * ----------------------------------------------------------------------------- */ -char *Swig_file_basename(const_String_or_char_ptr filename) { - static char tmp[1024]; - char *c; - strcpy(tmp, Char(filename)); - c = Swig_file_suffix(tmp); - *c = 0; - return tmp; +String *Swig_file_basename(const_String_or_char_ptr filename) { + String *extension = Swig_file_extension(filename); + String *basename = DohNewStringWithSize(filename, Len(filename) - Len(extension)); + Delete(extension); + return basename; } /* ----------------------------------------------------------------------------- * Swig_file_filename() * - * Return the file with any leading path stripped off + * Return the file name with any leading path stripped off * ----------------------------------------------------------------------------- */ -char *Swig_file_filename(const_String_or_char_ptr filename) { - static char tmp[1024]; +String *Swig_file_filename(const_String_or_char_ptr filename) { const char *delim = SWIG_FILE_DELIMITER; - char *c; - - strcpy(tmp, Char(filename)); - c = strrchr(tmp, *delim); - if (c) - return c + 1; - else - return tmp; + const char *c = strrchr(Char(filename), *delim); + return c ? NewString(c + 1) : NewString(filename); } /* ----------------------------------------------------------------------------- @@ -376,19 +367,10 @@ char *Swig_file_filename(const_String_or_char_ptr filename) { * * Return the name of the directory associated with a file * ----------------------------------------------------------------------------- */ -char *Swig_file_dirname(const_String_or_char_ptr filename) { - static char tmp[1024]; +String *Swig_file_dirname(const_String_or_char_ptr filename) { const char *delim = SWIG_FILE_DELIMITER; - char *c; - strcpy(tmp, Char(filename)); - if (!strstr(tmp, delim)) { - return ""; - } - c = tmp + strlen(tmp) - 1; - while (*c != *delim) - c--; - *(++c) = 0; - return tmp; + const char *c = strrchr(Char(filename), *delim); + return c ? NewStringWithSize(filename, c - Char(filename) + 1) : NewString(""); } /* diff --git a/Source/Swig/swigfile.h b/Source/Swig/swigfile.h index 158243c04..f12b33081 100644 --- a/Source/Swig/swigfile.h +++ b/Source/Swig/swigfile.h @@ -26,10 +26,10 @@ extern void Swig_set_push_dir(int dopush); extern int Swig_get_push_dir(void); extern void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile); extern File *Swig_filebyname(const_String_or_char_ptr filename); -extern char *Swig_file_suffix(const_String_or_char_ptr filename); -extern char *Swig_file_basename(const_String_or_char_ptr filename); -extern char *Swig_file_filename(const_String_or_char_ptr filename); -extern char *Swig_file_dirname(const_String_or_char_ptr filename); +extern String *Swig_file_extension(const_String_or_char_ptr filename); +extern String *Swig_file_basename(const_String_or_char_ptr filename); +extern String *Swig_file_filename(const_String_or_char_ptr filename); +extern String *Swig_file_dirname(const_String_or_char_ptr filename); extern void Swig_file_debug_set(); /* Delimiter used in accessing files and directories */