changeset 23540:61971e3f1946

avoid possible double free at interpreter exit (bug #51088) * symtab.cc (symbol_table::cleanup): Remove pointer to symbol table from all_instances map before deleting it. * symtab.h (symbol_table::erase_scope): Likewise.
author John W. Eaton <jwe@octave.org>
date Tue, 30 May 2017 12:30:44 -0400
parents 9578bbaf2bbd
children 0e4ceda8fbcf
files libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h
diffstat 2 files changed, 14 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/symtab.cc	Tue May 30 12:38:27 2017 -0400
+++ b/libinterp/corefcn/symtab.cc	Tue May 30 12:30:44 2017 -0400
@@ -1662,14 +1662,19 @@
   clear_all (true);
 
   // Delete all possibly remaining scopes.
-  for (auto& scope_stp : all_instances)
+
+  while (! all_instances.empty ())
     {
-      // First zero the table entry to avoid possible duplicate delete.
-      symbol_table *inst = scope_stp.second;
-      scope_stp.second = 0;
+      // Note that deleting a scope may have side effects such as
+      // deleting other scopes.  If another scope is deleted, it may
+      // invalidate ITER, so erase this map element first.
 
-      // Now delete the scope.
-      // Note that there may be side effects, such as deleting other scopes.
+      all_instances_iterator iter = all_instances.begin ();
+
+      symbol_table *inst = iter->second;
+
+      all_instances.erase (iter);
+
       delete inst;
     }
 
--- a/libinterp/corefcn/symtab.h	Tue May 30 12:38:27 2017 -0400
+++ b/libinterp/corefcn/symtab.h	Tue May 30 12:30:44 2017 -0400
@@ -1195,10 +1195,12 @@
 
     if (p != all_instances.end ())
       {
-        delete p->second;
+        symbol_table *inst = p->second;
 
         all_instances.erase (p);
 
+        delete inst;
+
         free_scope (scope);
       }
   }