changeset 24377:ea3458c1d884

improve handling of invalid symbol_scope objects (bug #52607) * symscope.h (class symbol_scope): Validate all uses of m_rep. (symbol_scope::symbol_scope (const std::string&)): Don't provide default argument value. Any named scope is considered valid, even if the name is "". (symbol_scope::symbol_scope (symbol_scope_rep *)): Provide default argument of nullptr. If m_rep is nullptr, then the scope is invalid.
author John W. Eaton <jwe@octave.org>
date Thu, 07 Dec 2017 01:31:34 -0500
parents 0755de78071c
children 64a85a19f6e3
files libinterp/corefcn/symscope.h libinterp/parse-tree/oct-parse.in.yy
diffstat 2 files changed, 118 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/symscope.h	Wed Dec 06 18:49:31 2017 -0800
+++ b/libinterp/corefcn/symscope.h	Thu Dec 07 01:31:34 2017 -0500
@@ -562,10 +562,15 @@
   {
   public:
 
-    symbol_scope (const std::string& name = "")
+    // Create a valid but possibly unnamed scope.
+    symbol_scope (const std::string& name)
       : m_rep (new symbol_scope_rep (name))
     { }
 
+    // NEW_REP must be dynamically allocated or nullptr.  If it is
+    // nullptr, the scope is invalid.
+    symbol_scope (symbol_scope_rep *new_rep = nullptr) : m_rep (new_rep) { }
+
     symbol_scope (const symbol_scope&) = default;
 
     symbol_scope& operator = (const symbol_scope&) = default;
@@ -578,314 +583,361 @@
 
     void insert_symbol_record (const symbol_record& sr)
     {
-      m_rep->insert_symbol_record (sr);
+      if (m_rep)
+        m_rep->insert_symbol_record (sr);
     }
 
     bool is_nested (void) const
     {
-      return m_rep->is_nested ();
+      return m_rep ? m_rep->is_nested () : false;
     }
 
     void mark_nested (void)
     {
-      m_rep->mark_nested ();
+      if (m_rep)
+        m_rep->mark_nested ();
     }
 
     bool is_static (void) const
     {
-      return m_rep->is_static ();
+      return m_rep ? m_rep->is_static () : false;
     }
 
     void mark_static (void)
     {
-      m_rep->mark_static ();
+      if (m_rep)
+        m_rep->mark_static ();
     }
 
     symbol_scope_rep * parent_scope (void) const
     {
-      return m_rep->parent_scope_rep ();
+      return m_rep ? m_rep->parent_scope_rep () : nullptr;
     }
 
     octave_value parent_fcn (void) const
     {
-      return m_rep->parent_fcn ();
+      return m_rep ? m_rep->parent_fcn () : octave_value ();
     }
 
     symbol_scope dup (void) const
     {
-      return symbol_scope (m_rep->dup ());
+      return symbol_scope (m_rep ? m_rep->dup () : nullptr);
     }
 
     void set_context (symbol_record::context_id context)
     {
-      m_rep->set_context (context);
+      if (m_rep)
+        m_rep->set_context (context);
     }
 
     symbol_record::context_id current_context (void) const
     {
-      return m_rep->current_context ();
+      return m_rep ? m_rep->current_context () : 0;
     }
 
     symbol_record find_symbol (const std::string& name)
     {
-      return m_rep->find_symbol (name);
+      return m_rep ? m_rep->find_symbol (name) : symbol_record ();
     }
 
     void inherit (const symbol_scope& donor_scope)
     {
-      m_rep->inherit (donor_scope.get_rep ());
+      if (m_rep)
+        m_rep->inherit (donor_scope.get_rep ());
     }
 
     octave_value
     find (const std::string& name, const octave_value_list& args,
           bool skip_variables, bool local_funcs)
     {
-      return m_rep->find (name, args, skip_variables, local_funcs);
+      return (m_rep
+              ? m_rep->find (name, args, skip_variables, local_funcs)
+              : octave_value ());
     }
 
     symbol_record&
     insert (const std::string& name, bool force_add = false)
     {
-      return m_rep->insert (name, force_add);
+      static symbol_record dummy_symrec;
+      return m_rep ? m_rep->insert (name, force_add) : dummy_symrec;
     }
 
     void rename (const std::string& old_name, const std::string& new_name)
     {
-      m_rep->rename (old_name, new_name);
+      if (m_rep)
+        m_rep->rename (old_name, new_name);
     }
 
     void assign (const std::string& name, const octave_value& value,
                  bool force_add)
     {
-      m_rep->assign (name, value, force_add);
+      if (m_rep)
+        m_rep->assign (name, value, force_add);
     }
 
     void assign (const std::string& name,
                  const octave_value& value = octave_value ())
     {
-      m_rep->assign (name, value);
+      if (m_rep)
+        m_rep->assign (name, value);
     }
 
     void force_assign (const std::string& name, const octave_value& value)
     {
-      m_rep->force_assign (name, value);
+      if (m_rep)
+        m_rep->force_assign (name, value);
     }
 
     octave_value varval (const std::string& name) const
     {
-      return m_rep->varval (name);
+      return m_rep ? m_rep->varval (name) : octave_value ();
     }
 
     bool is_variable (const std::string& name) const
     {
-      return m_rep->is_variable (name);
+      return m_rep ? m_rep->is_variable (name) : false;
     }
 
     void push_context (void)
     {
-      m_rep->push_context ();
+      if (m_rep)
+        m_rep->push_context ();
     }
 
     void pop_context (void)
     {
-      m_rep->pop_context ();
+      if (m_rep)
+        m_rep->pop_context ();
     }
 
     void refresh (void)
     {
-      m_rep->refresh ();
+      if (m_rep)
+        m_rep->refresh ();
     }
 
     void clear_variables (void)
     {
-      m_rep->clear_variables ();
+      if (m_rep)
+        m_rep->clear_variables ();
     }
 
     void clear_objects (void)
     {
-      m_rep->clear_objects ();
+      if (m_rep)
+        m_rep->clear_objects ();
     }
 
     void clear_variable (const std::string& name)
     {
-      m_rep->clear_variable (name);
+      if (m_rep)
+        m_rep->clear_variable (name);
     }
 
     void clear_variable_pattern (const std::string& pat)
     {
-      m_rep->clear_variable_pattern (pat);
+      if (m_rep)
+        m_rep->clear_variable_pattern (pat);
     }
 
     void clear_variable_regexp (const std::string& pat)
     {
-      m_rep->clear_variable_regexp (pat);
+      if (m_rep)
+        m_rep->clear_variable_regexp (pat);
     }
 
     void mark_automatic (const std::string& name)
     {
-      m_rep->mark_automatic (name);
+      if (m_rep)
+        m_rep->mark_automatic (name);
     }
 
     void mark_hidden (const std::string& name)
     {
-      m_rep->mark_hidden (name);
+      if (m_rep)
+        m_rep->mark_hidden (name);
     }
 
     void mark_global (const std::string& name)
     {
-      m_rep->mark_global (name);
+      if (m_rep)
+        m_rep->mark_global (name);
     }
 
     std::list<symbol_record>
     all_variables (bool defined_only = true,
                    unsigned int exclude = symbol_record::hidden) const
     {
-      return m_rep->all_variables (defined_only, exclude);
+      return (m_rep
+              ? m_rep->all_variables (defined_only, exclude)
+              : std::list<symbol_record> ());
     }
 
     std::list<symbol_record>
     glob (const std::string& pattern, bool vars_only = false) const
     {
-      return m_rep->glob (pattern, vars_only);
+      return (m_rep
+              ? m_rep->glob (pattern, vars_only)
+              : std::list<symbol_record> ());
     }
 
     std::list<symbol_record>
     regexp (const std::string& pattern, bool vars_only = false) const
     {
-      return m_rep->regexp (pattern, vars_only);
+      return (m_rep
+              ? m_rep->regexp (pattern, vars_only)
+              : std::list<symbol_record> ());
     }
 
     std::list<std::string> variable_names (void)
     {
-      return m_rep->variable_names ();
+      return m_rep ? m_rep->variable_names () : std::list<std::string> ();
     }
 
     bool is_local_variable (const std::string& name) const
     {
-      return m_rep->is_local_variable (name);
+      return m_rep ? m_rep->is_local_variable (name) : false;
     }
 
     bool is_global (const std::string& name) const
     {
-      return m_rep->is_global (name);
+      return m_rep ? m_rep->is_global (name) : false;
     }
 
     void install_subfunction (const std::string& name,
                               const octave_value& fval,
                               bool is_nested = false)
     {
-      m_rep->install_subfunction (name, fval, is_nested);
+      if (m_rep)
+        m_rep->install_subfunction (name, fval, is_nested);
     }
 
     void install_nestfunction (const std::string& name,
                                const octave_value& fval)
     {
-      m_rep->install_nestfunction (name, fval);
+      if (m_rep)
+        m_rep->install_nestfunction (name, fval);
     }
 
     octave_value find_subfunction (const std::string& name) const
     {
-      return m_rep->find_subfunction (name);
+      return m_rep ? m_rep->find_subfunction (name) : octave_value ();
     }
 
     void lock_subfunctions (void)
     {
-      m_rep->lock_subfunctions ();
+      if (m_rep)
+        m_rep->lock_subfunctions ();
     }
 
     void unlock_subfunctions (void)
     {
-      m_rep->unlock_subfunctions ();
+      if (m_rep)
+        m_rep->unlock_subfunctions ();
     }
 
     std::map<std::string, octave_value> subfunctions (void) const
     {
-      return m_rep->subfunctions ();
+      return (m_rep
+              ? m_rep->subfunctions ()
+              : std::map<std::string, octave_value> ());
     }
 
     void erase_subfunctions (void)
     {
-      m_rep->erase_subfunctions ();
+      if (m_rep)
+        m_rep->erase_subfunctions ();
     }
 
     void mark_subfunctions_in_scope_as_private (const std::string& class_name)
     {
-      m_rep->mark_subfunctions_in_scope_as_private (class_name);
+      if (m_rep)
+        m_rep->mark_subfunctions_in_scope_as_private (class_name);
     }
 
     bool has_subfunctions (void) const
     {
-      return m_rep->has_subfunctions ();
+      return m_rep ? m_rep->has_subfunctions () : false;
     }
 
     void stash_subfunction_names (const std::list<std::string>& names)
     {
-      m_rep->stash_subfunction_names (names);
+      if (m_rep)
+        m_rep->stash_subfunction_names (names);
     }
 
     std::list<std::string> subfunction_names (void) const
     {
-      return m_rep->subfunction_names ();
+      return m_rep ? m_rep->subfunction_names () : std::list<std::string> ();
     }
 
     std::list<workspace_element> workspace_info (void) const
     {
-      return m_rep->workspace_info ();
+      return (m_rep
+              ? m_rep->workspace_info ()
+              : std::list<workspace_element> ());
     }
 
     octave_value dump (void) const
     {
-      return m_rep->dump ();
+      return m_rep ? m_rep->dump () : octave_value ();
     }
 
     std::string name (void) const
     {
-      return m_rep->name ();
+      return m_rep ? m_rep->name () : "";
     }
 
     void cache_name (const std::string& name)
     {
-      m_rep->cache_name (name);
+      if (m_rep)
+        m_rep->cache_name (name);
     }
 
-    octave_user_function *function (void)
+    octave_user_function * function (void)
     {
-      return m_rep->function ();
+      return m_rep ? m_rep->function () : nullptr;
     }
 
     void set_function (octave_user_function *fcn)
     {
-      m_rep->set_function (fcn);
+      if (m_rep)
+        m_rep->set_function (fcn);
     }
 
     void set_parent (const symbol_scope& p)
     {
-      m_rep->set_parent (p.get_rep ());
+      if (m_rep)
+        m_rep->set_parent (p.get_rep ());
     }
 
     void set_parent (symbol_scope_rep *p)
     {
-      m_rep->set_parent (p);
+      if (m_rep)
+        m_rep->set_parent (p);
     }
 
     void update_nest (void)
     {
-      m_rep->update_nest ();
+      if (m_rep)
+        m_rep->update_nest ();
     }
 
     bool look_nonlocal (const std::string& name, symbol_record& result)
     {
-      return m_rep->look_nonlocal (name, result);
+      return m_rep ? m_rep->look_nonlocal (name, result) : false;
     }
 
     void bind_script_symbols (const symbol_scope& curr_scope)
     {
-      m_rep->bind_script_symbols (curr_scope.get_rep ());
+      if (m_rep)
+        m_rep->bind_script_symbols (curr_scope.get_rep ());
     }
 
     void unbind_script_symbols (void)
     {
-      m_rep->unbind_script_symbols ();
+      if (m_rep)
+        m_rep->unbind_script_symbols ();
     }
 
     symbol_scope_rep * get_rep (void) const
@@ -929,17 +981,14 @@
 
     std::shared_ptr<symbol_scope_rep> m_rep;
 
-    // NEW_REP must be dynamically allocated or nullptr.
-    symbol_scope (symbol_scope_rep *new_rep) : m_rep (new_rep) { }
-
     octave_value dump_symbols_map (void) const
     {
-      return m_rep->dump_symbols_map ();
+      return m_rep ? m_rep->dump_symbols_map () : octave_value ();
     }
 
     symbol_scope_rep * parent_scope_rep (void) const
     {
-      return m_rep->parent_scope_rep ();
+      return m_rep ? m_rep->parent_scope_rep () : nullptr;
     }
   };
 }
--- a/libinterp/parse-tree/oct-parse.in.yy	Wed Dec 06 18:49:31 2017 -0800
+++ b/libinterp/parse-tree/oct-parse.in.yy	Thu Dec 07 01:31:34 2017 -0500
@@ -1452,7 +1452,8 @@
                   {
                     $$ = 0;
 
-                    // Will get a real name later.
+                    // This scope may serve as the parent scope for local
+                    // functions in classdef files..
                     lexer.symtab_context.push (octave::symbol_scope ("parser:push_script_symtab"));
                   }
                 ;