# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1547806703 -3600
#      Fri Jan 18 11:18:23 2019 +0100
# Branch stable
# Node ID 72a856af4552a5e20a360effc1939e52f1a9bda5
# Parent  50439c2e8bbfe2ee9662fc465b6656642e6a1fb5
Avoid accumulating data in text_renderer member variable (bug #55287)

* ft-text-renderer.cc (m_do_strlist): New data member.
  (ft_text_renderer::text_to_strlist): Reset m_strlist before rendering.
  Unwind protect the value of m_do_strlist and m_strlist. Set m_do_strlist true
  prior to calling text_to_pixels. 
  (ft_text_renderer::visit (text_element_string)): Only feed the strlist when in
  MODE_RENDER and m_do_strlist is true.
  (ft_text_renderer::visit (text_element_symbol)): Dito.

diff -r 50439c2e8bbf -r 72a856af4552 libinterp/corefcn/ft-text-renderer.cc
--- a/libinterp/corefcn/ft-text-renderer.cc	Wed Jan 16 20:32:15 2019 -0800
+++ b/libinterp/corefcn/ft-text-renderer.cc	Fri Jan 18 11:18:23 2019 +0100
@@ -376,8 +376,9 @@
     ft_text_renderer (void)
       : base_text_renderer (), font (), bbox (1, 4, 0.0), halign (0),
         xoffset (0), line_yoffset (0), yoffset (0), mode (MODE_BBOX),
-        color (dim_vector (1, 3), 0), line_xoffset (0), m_ymin (0), m_ymax (0),
-        m_deltax (0), m_max_fontsize (0)
+        color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (),
+        line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0),
+        m_max_fontsize (0)
     { }
 
     // No copying!
@@ -530,7 +531,8 @@
     uint8NDArray color;
 
     // A list of parsed strings to be used for printing.
-    std::list<text_renderer::string> strlist;
+    bool m_do_strlist;
+    std::list<text_renderer::string> m_strlist;
 
     // The X offset of the baseline for the current line.
     int line_xoffset;
@@ -862,9 +864,16 @@
 
     // First run text_to_pixels which will also build the string list
 
+    m_strlist = std::list<text_renderer::string> ();
+    
+    octave::unwind_protect frame;
+    frame.protect_var (m_do_strlist);
+    frame.protect_var (m_strlist);
+    m_do_strlist = true;
+    
     text_to_pixels (txt, pxls, box, ha, va, rot, interp, false);
 
-    lst = strlist;
+    lst = m_strlist;
   }
 
   void
@@ -894,38 +903,44 @@
             // character
             int mblen = octave_u8_strmbtouc_wrapper (&u32_c, c + icurr);
             n -= mblen;
-            
-            if (u32_c == 10)
+
+            if (m_do_strlist && mode == MODE_RENDER)
               {
-                // Finish previous string in strlist before processing
-                // the newline character
-                fs.set_y (line_yoffset + yoffset);
-                fs.set_color (color);
+                if (u32_c == 10)
+                  {
+                    // Finish previous string in m_strlist before processing
+                    // the newline character
+                    fs.set_y (line_yoffset + yoffset);
+                    fs.set_color (color);
                 
-                std::string s = str.substr (ibegin, icurr - ibegin);
-                if (! s.empty ())
-                  {
-                    fs.set_string (s);
-                    fs.set_y (line_yoffset + yoffset);
-                    fs.set_xdata (xdata);
-                    fs.set_family (fname);
-                    strlist.push_back (fs);
+                    std::string s = str.substr (ibegin, icurr - ibegin);
+                    if (! s.empty ())
+                      {
+                        fs.set_string (s);
+                        fs.set_y (line_yoffset + yoffset);
+                        fs.set_xdata (xdata);
+                        fs.set_family (fname);
+                        m_strlist.push_back (fs);
+                      }
                   }
+                else
+                  xdata.push_back (xoffset);
               }
-            else
-              xdata.push_back (xoffset);
 
             glyph_index = process_character (u32_c, previous);
 
-
             if (u32_c == 10)
               {
                 previous = 0;
-                // Start a new string in strlist
-                ibegin = icurr+1;
-                xdata.clear ();
-                fs = text_renderer::string (str.substr (ibegin), font,
+                
+                if (m_do_strlist && mode == MODE_RENDER)
+                  {
+                    // Start a new string in m_strlist
+                    ibegin = icurr+1;
+                    xdata.clear ();
+                    fs = text_renderer::string (str.substr (ibegin), font,
                                             line_xoffset, yoffset);
+                  }
               }
             else
               previous = glyph_index;
@@ -933,13 +948,13 @@
             icurr += mblen;
           }
 
-        if (! fs.get_string ().empty ())
+        if (m_do_strlist && mode == MODE_RENDER && ! fs.get_string ().empty ())
           {
             fs.set_y (line_yoffset + yoffset);
             fs.set_color (color);
             fs.set_xdata (xdata);
             fs.set_family (fname);
-            strlist.push_back (fs);
+            m_strlist.push_back (fs);
           }
       }
   }
@@ -1088,18 +1103,21 @@
     if (code != text_element_symbol::invalid_code && font.is_valid ())
       {
         process_character (code);
-        fs.set_code (code);
-        fs.set_xdata (xdata);
+        if (m_do_strlist && mode == MODE_RENDER)
+          {
+            fs.set_code (code);
+            fs.set_xdata (xdata);
+          }
       }
     else if (font.is_valid ())
       ::warning ("ignoring unknown symbol: %d", e.get_symbol ());
 
-    if (fs.get_code ())
+    if (m_do_strlist && mode == MODE_RENDER && fs.get_code ())
       {
         fs.set_y (line_yoffset + yoffset);
         fs.set_color (color);
         fs.set_family (font.get_face ()->family_name);
-        strlist.push_back (fs);
+        m_strlist.push_back (fs);
       }
   }
 
@@ -1124,6 +1142,7 @@
   {
     set_mode (MODE_BBOX);
     set_color (Matrix (1, 3, 0.0));
+    m_strlist = std::list<text_renderer::string> ();
   }
 
   void
@@ -1148,8 +1167,6 @@
     box = bbox;
 
     set_mode (MODE_RENDER);
-    // Clear the list of parsed strings
-    strlist.clear ();
 
     if (pixels.numel () > 0)
       {
