# HG changeset patch # User John W. Eaton # Date 1323032278 18000 # Node ID 051a8f94b6f8419ecbf7efa22c3a06b766125c1c # Parent c9a0e5343cd8894ef9eadc9e8fdf7ed11551186f 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. diff -r c9a0e5343cd8 -r 051a8f94b6f8 build-aux/bootstrap.conf --- a/build-aux/bootstrap.conf Sun Dec 04 03:38:45 2011 -0500 +++ b/build-aux/bootstrap.conf Sun Dec 04 15:57:58 2011 -0500 @@ -74,6 +74,7 @@ truncf unistd unlink + vasprintf vsnprintf " diff -r c9a0e5343cd8 -r 051a8f94b6f8 src/utils.cc --- a/src/utils.cc Sun Dec 04 03:38:45 2011 -0500 +++ b/src/utils.cc Sun Dec 04 15:57:58 2011 -0500 @@ -36,6 +36,8 @@ #include #include +#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(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); diff -r c9a0e5343cd8 -r 051a8f94b6f8 src/utils.h --- a/src/utils.h Sun Dec 04 03:38:45 2011 -0500 +++ b/src/utils.h Sun Dec 04 15:57:58 2011 -0500 @@ -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);