changeset 21517:e626d8a3427e

avoid possible memory leak related to ostringstream objects * oct-stream.cc (scanf_format_list::buf, printf_format_list::buf, textscan_format_list:buf): Use std::ostringstream object instead of a pointer to one that must be allocated. Instead of deleting, clear flags and initialize internal string buffer. Update all uses.
author John W. Eaton <jwe@octave.org>
date Mon, 21 Mar 2016 22:37:34 -0400
parents ba9d1a17f563
children 2ee20a290d61
files libinterp/corefcn/oct-stream.cc
diffstat 1 files changed, 125 insertions(+), 125 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Mon Mar 21 22:23:13 2016 -0400
+++ b/libinterp/corefcn/oct-stream.cc	Mon Mar 21 22:37:34 2016 -0400
@@ -304,7 +304,7 @@
   std::deque<scanf_format_elt*> fmt_elts;
 
   // Temporary buffer.
-  std::ostringstream *buf;
+  std::ostringstream buf;
 
   void add_elt_to_list (int width, bool discard, char type, char modifier,
                         const std::string& char_class = "");
@@ -324,7 +324,7 @@
 };
 
 scanf_format_list::scanf_format_list (const std::string& s)
-  : nconv (0), curr_idx (0), fmt_elts (), buf (0)
+  : nconv (0), curr_idx (0), fmt_elts (), buf ()
 {
   size_t n = s.length ();
 
@@ -341,16 +341,13 @@
     {
       have_more = true;
 
-      if (! buf)
-        buf = new std::ostringstream ();
-
       if (s[i] == '%')
         {
           // Process percent-escape conversion type.
 
           process_conversion (s, i, n, width, discard, type, modifier);
 
-          have_more = (buf != 0);
+          have_more = (buf.tellp () != 0);
         }
       else if (isspace (s[i]))
         {
@@ -359,7 +356,7 @@
           width = 0;
           discard = false;
           modifier = '\0';
-          *buf << " ";
+          buf << " ";
 
           while (++i < n && isspace (s[i]))
             ; // skip whitespace
@@ -377,7 +374,7 @@
           modifier = '\0';
 
           while (i < n && ! isspace (s[i]) && s[i] != '%')
-            *buf << s[i++];
+            buf << s[i++];
 
           add_elt_to_list (width, discard, type, modifier);
 
@@ -394,7 +391,8 @@
   if (have_more)
     add_elt_to_list (width, discard, type, modifier);
 
-  delete buf;
+  buf.clear ();
+  buf.str ("");
 }
 
 scanf_format_list::~scanf_format_list (void)
@@ -413,22 +411,19 @@
                                     char modifier,
                                     const std::string& char_class)
 {
-  if (buf)
-    {
-      std::string text = buf->str ();
-
-      if (! text.empty ())
-        {
-          scanf_format_elt *elt
-            = new scanf_format_elt (text.c_str (), width, discard, type,
-                                    modifier, char_class);
-
-          fmt_elts.push_back (elt);
-        }
-
-      delete buf;
-      buf = 0;
-    }
+  std::string text = buf.str ();
+
+  if (! text.empty ())
+    {
+      scanf_format_elt *elt
+        = new scanf_format_elt (text.c_str (), width, discard, type,
+                                modifier, char_class);
+
+      fmt_elts.push_back (elt);
+    }
+
+  buf.clear ();
+  buf.str ("");
 }
 
 static std::string
@@ -477,7 +472,7 @@
   modifier = '\0';
   type = '\0';
 
-  *buf << s[i++];
+  buf << s[i++];
 
   bool have_width = false;
 
@@ -491,7 +486,7 @@
           else
             {
               discard = true;
-              *buf << s[i++];
+              buf << s[i++];
             }
           break;
 
@@ -504,12 +499,12 @@
               char c = s[i++];
               width = 10 * width + c - '0';
               have_width = true;
-              *buf << c;
+              buf << c;
               while (i < n && isdigit (s[i]))
                 {
                   c = s[i++];
                   width = 10 * width + c - '0';
-                  *buf << c;
+                  buf << c;
                 }
             }
           break;
@@ -537,7 +532,7 @@
             }
 
           // No float or long double conversions, thanks.
-          *buf << 'l';
+          buf << 'l';
 
           goto fini;
 
@@ -584,7 +579,7 @@
   if (s[i] == '%')
     {
       type = '%';
-      *buf << s[i++];
+      buf << s[i++];
     }
   else
     {
@@ -592,7 +587,7 @@
 
       if (s[i] == '[')
         {
-          *buf << s[i++];
+          buf << s[i++];
 
           if (i < n)
             {
@@ -601,34 +596,34 @@
               if (s[i] == '^')
                 {
                   type = '^';
-                  *buf << s[i++];
+                  buf << s[i++];
 
                   if (i < n)
                     {
                       beg_idx = i;
 
                       if (s[i] == ']')
-                        *buf << s[i++];
+                        buf << s[i++];
                     }
                 }
               else if (s[i] == ']')
-                *buf << s[i++];
+                buf << s[i++];
             }
 
           while (i < n && s[i] != ']')
-            *buf << s[i++];
+            buf << s[i++];
 
           if (i < n && s[i] == ']')
             {
               end_idx = i-1;
-              *buf << s[i++];
+              buf << s[i++];
             }
 
           if (s[i-1] != ']')
             retval = nconv = -1;
         }
       else
-        *buf << s[i++];
+        buf << s[i++];
 
       nconv++;
     }
@@ -850,7 +845,7 @@
   std::deque<printf_format_elt*> fmt_elts;
 
   // Temporary buffer.
-  std::ostringstream *buf;
+  std::ostringstream buf;
 
   void add_elt_to_list (int args, const std::string& flags, int fw,
                         int prec, char type, char modifier);
@@ -871,7 +866,7 @@
 };
 
 printf_format_list::printf_format_list (const std::string& s)
-  : nconv (0), curr_idx (0), fmt_elts (), buf (0)
+  : nconv (0), curr_idx (0), fmt_elts (), buf ()
 {
   size_t n = s.length ();
 
@@ -900,11 +895,7 @@
         {
           have_more = true;
 
-          if (! buf)
-            {
-              buf = new std::ostringstream ();
-              empty_buf = true;
-            }
+          empty_buf = (buf.tellp () == 0);
 
           switch (s[i])
             {
@@ -915,7 +906,13 @@
                     process_conversion (s, i, n, args, flags, fw, prec,
                                         type, modifier);
 
-                    have_more = (buf != 0);
+                    // If there is nothing in the buffer, then
+                    // add_elt_to_list must have just been called, so we
+                    // are already done with the current element and we
+                    // don't need to call add_elt_to_list if this is our
+                    // last trip through the loop.
+
+                    have_more = (buf.tellp () != 0);
                   }
                 else
                   add_elt_to_list (args, flags, fw, prec, type, modifier);
@@ -930,7 +927,7 @@
                 prec = -1;
                 modifier = '\0';
                 type = '\0';
-                *buf << s[i++];
+                buf << s[i++];
                 empty_buf = false;
               }
               break;
@@ -946,7 +943,8 @@
       if (have_more)
         add_elt_to_list (args, flags, fw, prec, type, modifier);
 
-      delete buf;
+      buf.clear ();
+      buf.str ("");
     }
 }
 
@@ -966,22 +964,19 @@
                                      int fw, int prec, char type,
                                      char modifier)
 {
-  if (buf)
-    {
-      std::string text = buf->str ();
-
-      if (! text.empty ())
-        {
-          printf_format_elt *elt
-            = new printf_format_elt (text.c_str (), args, fw, prec, flags,
-                                     type, modifier);
-
-          fmt_elts.push_back (elt);
-        }
-
-      delete buf;
-      buf = 0;
-    }
+  std::string text = buf.str ();
+
+  if (! text.empty ())
+    {
+      printf_format_elt *elt
+        = new printf_format_elt (text.c_str (), args, fw, prec, flags,
+                                 type, modifier);
+
+      fmt_elts.push_back (elt);
+    }
+
+  buf.clear ();
+  buf.str ("");
 }
 
 void
@@ -998,7 +993,7 @@
   modifier = '\0';
   type = '\0';
 
-  *buf << s[i++];
+  buf << s[i++];
 
   bool nxt = false;
 
@@ -1008,7 +1003,7 @@
         {
         case '-': case '+': case ' ': case '0': case '#':
           flags += s[i];
-          *buf << s[i++];
+          buf << s[i++];
           break;
 
         default:
@@ -1026,7 +1021,7 @@
         {
           fw = -2;
           args++;
-          *buf << s[i++];
+          buf << s[i++];
         }
       else
         {
@@ -1038,7 +1033,7 @@
             }
 
           while (i < n && isdigit (s[i]))
-            *buf << s[i++];
+            buf << s[i++];
         }
     }
 
@@ -1051,7 +1046,7 @@
       // . followed by nothing is 0.
       prec = 0;
 
-      *buf << s[i++];
+      buf << s[i++];
 
       if (i < n)
         {
@@ -1059,7 +1054,7 @@
             {
               prec = -2;
               args++;
-              *buf << s[i++];
+              buf << s[i++];
             }
           else
             {
@@ -1071,7 +1066,7 @@
                 }
 
               while (i < n && isdigit (s[i]))
-                *buf << s[i++];
+                buf << s[i++];
             }
         }
     }
@@ -1136,7 +1131,7 @@
 
       type = s[i];
 
-      *buf << s[i++];
+      buf << s[i++];
 
       if (type != '%' || args != 0)
         nconv++;
@@ -1733,7 +1728,7 @@
   std::list<octave_value> output_container;
 
   // Temporary buffer.
-  std::ostringstream *buf;
+  std::ostringstream buf;
 
   void add_elt_to_list (unsigned int width, int prec, int bitwidth,
                         octave_value val_type, bool discard,
@@ -1911,7 +1906,7 @@
 textscan_format_list::textscan_format_list (const std::string& s,
                                             const std::string& who_arg)
   : who (who_arg), set_from_first (false), has_string (false),
-    nconv (0), curr_idx (0), fmt_elts (), buf (0)
+    nconv (0), curr_idx (0), fmt_elts (), buf ()
 {
   size_t n = s.length ();
 
@@ -1927,7 +1922,11 @@
 
   if (s.empty ())
     {
-      buf = new std::ostringstream ("%f");
+      buf.clear ();
+      buf.str ("");
+
+      buf << "%f";
+
       bitwidth = 64;
       type = 'f';
       add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()),
@@ -1944,16 +1943,19 @@
         {
           have_more = true;
 
-          if (! buf)
-            buf = new std::ostringstream ();
-
           if (s[i] == '%' && (i+1 == n || s[i+1] != '%'))
             {
               // Process percent-escape conversion type.
 
               process_conversion (s, i, n);
 
-              have_more = (buf != 0);
+              // If there is nothing in the buffer, then add_elt_to_list
+              // must have just been called, so we are already done with
+              // the current element and we don't need to call
+              // add_elt_to_list if this is our last trip through the
+              // loop.
+
+              have_more = (buf.tellp () != 0);
             }
           else if (isspace (s[i]))
             {
@@ -1976,7 +1978,7 @@
                 {
                   if (s[i] == '%')      // if double %, skip one
                     i++;
-                  *buf << s[i++];
+                  buf << s[i++];
                   width++;
                 }
 
@@ -1997,7 +1999,8 @@
   if (have_more)
     add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type);
 
-  delete buf;
+  buf.clear ();
+  buf.str ("");
 }
 
 textscan_format_list::~textscan_format_list (void)
@@ -2017,24 +2020,21 @@
                                        bool discard, char type,
                                        const std::string& char_class)
 {
-  if (buf)
-    {
-      std::string text = buf->str ();
-
-      if (! text.empty ())
-        {
-          textscan_format_elt *elt
-            = new textscan_format_elt (text, width, prec, bitwidth, discard, type, char_class);
-
-          if (! discard)
-            output_container.push_back (val_type);
-
-          fmt_elts.push_back (elt);
-        }
-
-      delete buf;
-      buf = 0;
-    }
+  std::string text = buf.str ();
+
+  if (! text.empty ())
+    {
+      textscan_format_elt *elt
+        = new textscan_format_elt (text, width, prec, bitwidth, discard, type, char_class);
+
+      if (! discard)
+        output_container.push_back (val_type);
+
+      fmt_elts.push_back (elt);
+    }
+
+  buf.clear ();
+  buf.str ("");
 }
 
 void
@@ -2048,7 +2048,7 @@
   octave_value val_type;
   char type = '\0';
 
-  *buf << s[i++];
+  buf << s[i++];
 
   bool have_width = false;
 
@@ -2062,7 +2062,7 @@
           else
             {
               discard = true;
-              *buf << s[i++];
+              buf << s[i++];
             }
           break;
 
@@ -2075,23 +2075,23 @@
               char c = s[i++];
               width = width * 10 + c - '0';
               have_width = true;
-              *buf << c;
+              buf << c;
               while (i < n && isdigit (s[i]))
                 {
                   c = s[i++];
                   width = width * 10 + c - '0';
-                  *buf << c;
+                  buf << c;
                 }
 
               if (i < n && s[i] == '.')
                 {
-                  *buf << s[i++];
+                  buf << s[i++];
                   prec = 0;
                   while (i < n && isdigit (s[i]))
                     {
                       c = s[i++];
                       prec = prec * 10 + c - '0';
-                      *buf << c;
+                      buf << c;
                     }
                 }
             }
@@ -2100,7 +2100,7 @@
         case 'd': case 'u':
           {
             bool done = true;
-            *buf << (type = s[i++]);
+            buf << (type = s[i++]);
             if (i < n)
               {
                 if (s[i] == '8')
@@ -2110,7 +2110,7 @@
                       val_type = octave_value (int8NDArray ());
                     else
                       val_type = octave_value (uint8NDArray ());
-                    *buf << s[i++];
+                    buf << s[i++];
                   }
                 else if (s[i] == '1' && i+1 < n && s[i+1] == '6')
                   {
@@ -2119,14 +2119,14 @@
                       val_type = octave_value (int16NDArray ());
                     else
                       val_type = octave_value (uint16NDArray ());
-                    *buf << s[i++];
-                    *buf << s[i++];
+                    buf << s[i++];
+                    buf << s[i++];
                   }
                 else if (s[i] == '3' && i+1 < n && s[i+1] == '2')
                   {
                     done = false;       // use default size below
-                    *buf << s[i++];
-                    *buf << s[i++];
+                    buf << s[i++];
+                    buf << s[i++];
                   }
                 else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
                   {
@@ -2135,8 +2135,8 @@
                       val_type = octave_value (int64NDArray ());
                     else
                       val_type = octave_value (uint64NDArray ());
-                    *buf << s[i++];
-                    *buf << s[i++];
+                    buf << s[i++];
+                    buf << s[i++];
                   }
                 else
                   done = false;
@@ -2156,7 +2156,7 @@
           }
 
         case 'f':
-          *buf << (type = s[i++]);
+          buf << (type = s[i++]);
           bitwidth = 64;
           if (i < n)
             {
@@ -2164,14 +2164,14 @@
                 {
                   bitwidth = 32;
                   val_type = octave_value (FloatNDArray ());
-                  *buf << s[i++];
-                  *buf << s[i++];
+                  buf << s[i++];
+                  buf << s[i++];
                 }
               else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
                 {
                   val_type = octave_value (NDArray ());
-                  *buf << s[i++];
-                  *buf << s[i++];
+                  buf << s[i++];
+                  buf << s[i++];
                 }
               else
                 val_type = octave_value (NDArray ());
@@ -2181,7 +2181,7 @@
           goto fini;
 
         case 'n':
-          *buf << (type = s[i++]);
+          buf << (type = s[i++]);
           bitwidth = 64;
           val_type = octave_value (NDArray ());
           goto fini;
@@ -2189,7 +2189,7 @@
         case 's': case 'q': case '[': case 'c':
           if (! discard)
             val_type = octave_value (Cell ());
-          *buf << (type = s[i++]);
+          buf << (type = s[i++]);
           has_string = true;
           goto fini;
 
@@ -2346,27 +2346,27 @@
               if (s[i] == '^')
                 {
                   type = '^';
-                  *buf << s[i++];
+                  buf << s[i++];
 
                   if (i < n)
                     {
                       beg_idx = i;
 
                       if (s[i] == ']')
-                        *buf << s[i++];
+                        buf << s[i++];
                     }
                 }
               else if (s[i] == ']')
-                *buf << s[i++];
+                buf << s[i++];
             }
 
           while (i < n && s[i] != ']')
-            *buf << s[i++];
+            buf << s[i++];
 
           if (i < n && s[i] == ']')
             {
               end_idx = i-1;
-              *buf << s[i++];
+              buf << s[i++];
             }
 
           if (s[i-1] != ']')