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	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
 "
 
--- 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 <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	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);