Mercurial > hg > octave-lojdl
changeset 13991:051a8f94b6f8
avoid memory issue with octave_vsnprintf
* utils.h, utils.cc (octave_vsnprintf, octave_snprintf):
Return std::string, not char *.
(octave_vformat, octave_format): Return size_t, not int.
(octave_vsnprintf): Simplify implementation with vasprintf.
Include gnulib vasprintf.h from gnulib.
* bootstrap.conf (gnulib_modules): Include vasprintf in the list.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sun, 04 Dec 2011 15:57:58 -0500 |
parents | c9a0e5343cd8 |
children | e1f76bfe0452 |
files | build-aux/bootstrap.conf src/utils.cc src/utils.h |
diffstat | 3 files changed, 27 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/build-aux/bootstrap.conf +++ b/build-aux/bootstrap.conf @@ -74,6 +74,7 @@ truncf unistd unlink + vasprintf vsnprintf "
--- a/src/utils.cc +++ b/src/utils.cc @@ -36,6 +36,8 @@ #include <sys/types.h> #include <unistd.h> +#include "vasnprintf.h" + #include "quit.h" #include "dir-ops.h" @@ -1194,10 +1196,10 @@ return m; } -int +size_t octave_format (std::ostream& os, const char *fmt, ...) { - int retval = -1; + size_t retval; va_list args; va_start (args, fmt); @@ -1209,118 +1211,38 @@ return retval; } -int +size_t octave_vformat (std::ostream& os, const char *fmt, va_list args) { - int retval = -1; + std::string s = octave_vsnprintf (fmt, args); -#if defined (__GNUG__) && !CXX_ISO_COMPLIANT_LIBRARY + os << s; - std::streambuf *sb = os.rdbuf (); + return s.length (); +} - if (sb) - { - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; +std::string +octave_vsnprintf (const char *fmt, va_list args) +{ + std::string retval; + + char *result; - retval = sb->vform (fmt, args); + int status = vasprintf (&result, fmt, args); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + if (status >= 0) + { + retval = result; + ::free (result); } -#else - - char *s = octave_vsnprintf (fmt, args); - - if (s) - { - os << s; - - retval = strlen (s); - } - -#endif - return retval; } -// We manage storage. User should not free it, and its contents are -// only valid until next call to vsnprintf. - -// Interrupts might happen if someone makes a call with something that -// will require a very large buffer. If we are interrupted in that -// case, we should make the buffer size smaller for the next call. - -#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF \ - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \ - delete [] buf; \ - buf = 0; \ - size = initial_size; \ - octave_rethrow_exception (); \ - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2 - -#if defined __GNUC__ && defined __va_copy -#define SAVE_ARGS(saved_args, args) __va_copy (saved_args, args) -#elif defined va_copy -#define SAVE_ARGS(saved_args, args) va_copy (saved_args, args) -#else -#define SAVE_ARGS(saved_args, args) saved_args = args -#endif - -char * -octave_vsnprintf (const char *fmt, va_list args) -{ - static const size_t initial_size = 100; - - static size_t size = initial_size; - - static char *buf = 0; - - volatile int nchars = 0; - - if (! buf) - buf = new char [size]; - - if (! buf) - return 0; - - while (1) - { - va_list saved_args; - - SAVE_ARGS (saved_args, args); - - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF; - - nchars = octave_raw_vsnprintf (buf, size, fmt, saved_args); - - va_end (saved_args); - - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - - // Cast to avoid signed/unsigned comparison is safe due to - // short-circuiting - if (nchars > -1 && static_cast<size_t>(nchars) < size) - break; - else - { - delete [] buf; - - size = nchars + 1;; - - buf = new char [size]; - - if (! buf) - return 0; - } - } - - return buf; -} - -char * +std::string octave_snprintf (const char *fmt, ...) { - char *retval = 0; + std::string retval; va_list args; va_start (args, fmt);
--- a/src/utils.h +++ b/src/utils.h @@ -103,15 +103,15 @@ extern OCTINTERP_API FloatMatrix float_identity_matrix (octave_idx_type nr, octave_idx_type nc); -extern OCTINTERP_API int +extern OCTINTERP_API size_t octave_format (std::ostream& os, const char *fmt, ...); -extern OCTINTERP_API int +extern OCTINTERP_API size_t octave_vformat (std::ostream& os, const char *fmt, va_list args); -extern OCTINTERP_API char *octave_vsnprintf (const char *fmt, va_list args); +extern OCTINTERP_API std::string octave_vsnprintf (const char *fmt, va_list args); -extern OCTINTERP_API char *octave_snprintf (const char *fmt, ...); +extern OCTINTERP_API std::string octave_snprintf (const char *fmt, ...); extern OCTINTERP_API void octave_sleep (double seconds);