changeset 26512:4d6392c879d7 stable

avoid double free of lexer on exit (bug #55347) * parse.h (parser::parser): Accept pointer to lexer object instead of reference. Comment to state that lexer object must be allocated by new and will be deleted by the parser destructor. * pt-eval.cc (tree_evaluator::repl): Construct parser using pointer to lexer. Don't delete lexer object. (tree_evaluator::repl, tree_evaluator::eval_string): Avoid confusing "parser parser" declaration by renaming parser objects to be repl_parser and eval_parser, respectively.
author John W. Eaton <jwe@octave.org>
date Wed, 09 Jan 2019 14:49:01 -0500
parents 7bf8036ad3f6
children 32890ede698c 02a9e1bb314a
files libinterp/parse-tree/parse.h libinterp/parse-tree/pt-eval.cc
diffstat 2 files changed, 26 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/parse.h	Wed Jan 09 09:05:31 2019 +0100
+++ b/libinterp/parse-tree/parse.h	Wed Jan 09 14:49:01 2019 -0500
@@ -498,8 +498,12 @@
       : base_parser (*(new lexer (eval_string, interp)))
     { }
 
-    parser (lexer& lxr)
-      : base_parser (lxr)
+    // The lexer must be allocated with new.  The parser object
+    // takes ownership of and deletes the lexer object in its
+    // destructor.
+
+    parser (lexer *lxr)
+      : base_parser (*lxr)
     { }
 
     // No copying!
--- a/libinterp/parse-tree/pt-eval.cc	Wed Jan 09 09:05:31 2019 +0100
+++ b/libinterp/parse-tree/pt-eval.cc	Wed Jan 09 14:49:01 2019 -0500
@@ -77,11 +77,12 @@
   {
     int retval = 0;
 
-    lexer *lxr = (interactive
-                  ? new lexer (m_interpreter)
-                  : new lexer (stdin, m_interpreter));
-
-    parser parser (*lxr);
+    // The parser takes ownership of the lexer and will delete it when
+    // the parser goes out of scope.
+
+    parser repl_parser (interactive
+                        ? new lexer (m_interpreter)
+                        : new lexer (stdin, m_interpreter));
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
@@ -91,18 +92,18 @@
           {
             reset_error_handler ();
 
-            parser.reset ();
+            repl_parser.reset ();
 
             if (symtab.at_top_level ())
               reset_debug_state ();
 
-            retval = parser.run ();
+            retval = repl_parser.run ();
 
             if (retval == 0)
               {
-                if (parser.m_stmt_list)
+                if (repl_parser.m_stmt_list)
                   {
-                    parser.m_stmt_list->accept (*this);
+                    repl_parser.m_stmt_list->accept (*this);
 
                     octave_quit ();
 
@@ -125,7 +126,7 @@
                     else
                       command_editor::increment_current_command_number ();
                   }
-                else if (parser.m_lexer.m_end_of_input)
+                else if (repl_parser.m_lexer.m_end_of_input)
                   {
                     retval = EOF;
                     break;
@@ -190,9 +191,6 @@
         retval = 0;
       }
 
-    // Clean up memory
-    delete lxr;
-
     return retval;
   }
 
@@ -202,22 +200,22 @@
   {
     octave_value_list retval;
 
-    parser parser (eval_str, m_interpreter);
+    parser eval_parser (eval_str, m_interpreter);
 
     do
       {
-        parser.reset ();
-
-        parse_status = parser.run ();
+        eval_parser.reset ();
+
+        parse_status = eval_parser.run ();
 
         if (parse_status == 0)
           {
-            if (parser.m_stmt_list)
+            if (eval_parser.m_stmt_list)
               {
                 tree_statement *stmt = nullptr;
 
-                if (parser.m_stmt_list->length () == 1
-                    && (stmt = parser.m_stmt_list->front ())
+                if (eval_parser.m_stmt_list->length () == 1
+                    && (stmt = eval_parser.m_stmt_list->front ())
                     && stmt->is_expression ())
                   {
                     tree_expression *expr = stmt->expression ();
@@ -251,14 +249,14 @@
                       retval = octave_value_list ();
                   }
                 else if (nargout == 0)
-                  parser.m_stmt_list->accept (*this);
+                  eval_parser.m_stmt_list->accept (*this);
                 else
                   error ("eval: invalid use of statement list");
 
                 if (returning () || breaking () || continuing ())
                   break;
               }
-            else if (parser.m_lexer.m_end_of_input)
+            else if (eval_parser.m_lexer.m_end_of_input)
               break;
           }
       }