changeset 16285:3389152014ca

improve validation of left hand side of assignment expressions in parser * pt-arg-list.cc (tree_argument_list::is_valid_lvalue_list): * oct-parse.in.yy (octave_parser::validate_for_assignment): Improve checks.
author John W. Eaton <jwe@octave.org>
date Mon, 11 Mar 2013 18:19:10 -0400
parents 09881dab3aaf
children f58257a6d18c 04a7953496a7
files libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-arg-list.h
diffstat 3 files changed, 61 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.in.yy	Mon Mar 11 17:20:34 2013 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Mar 11 18:19:10 2013 -0400
@@ -2947,29 +2947,46 @@
 
   if (e->is_constant ())
     {
-      bison_error ("invalid empty LHS in [] = ... assignment");
+      octave_value ov = e->rvalue1 ();
+
+      if (ov.is_empty ())
+        bison_error ("invalid empty left hand side of assignment");
+      else
+        bison_error ("invalid constant left hand side of assignment");
+
       delete e;
     }
-  else if (e->is_matrix ())
-    {
-      tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
-
-      if (mat && mat->size () == 1)
-        {
-          retval = mat->front ();
-          mat->pop_front ();
-          delete e;
-        }
-      else
-        {
-          bison_error ("invalid LHS in '[LHS] = ...' assignment");
-          delete e;
-        }
-    }
   else
     {
-      retval = new tree_argument_list (e);
-      retval->mark_as_simple_assign_lhs ();
+      bool is_simple_assign = true;
+
+      tree_argument_list *tmp = 0;
+
+      if (e->is_matrix ())
+        {
+          tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
+
+          if (mat && mat->size () == 1)
+            {
+              tmp = mat->front ();
+              mat->pop_front ();
+              delete e;
+              is_simple_assign = false;
+            }
+        }
+      else
+        tmp = new tree_argument_list (e);
+
+      if (tmp && tmp->is_valid_lvalue_list ())
+        retval = tmp;
+      else
+        {
+          bison_error ("invalid left hand side of assignment");
+          delete tmp;
+        }
+
+      if (retval && is_simple_assign)
+        retval->mark_as_simple_assign_lhs ();
     }
 
   return retval;
--- a/libinterp/parse-tree/pt-arg-list.cc	Mon Mar 11 17:20:34 2013 -0400
+++ b/libinterp/parse-tree/pt-arg-list.cc	Mon Mar 11 18:19:10 2013 -0400
@@ -99,6 +99,29 @@
   return true;
 }
 
+bool
+tree_argument_list::is_valid_lvalue_list (void) const
+{
+  bool retval = true;
+
+  for (const_iterator p = begin (); p != end (); p++)
+    {
+      tree_expression *elt = *p;
+
+      // There is no need for a separate check for the magic "~" because
+      // it represented by tree_black_hole, and that is derived from
+      // tree_identifier.
+
+      if (! (elt->is_identifier () || elt->is_index_expression ()))
+        {
+          retval = false;
+          break;
+        }
+    }
+
+  return retval;
+}
+
 static const octave_value *indexed_object = 0;
 static int index_position = 0;
 static int num_indices = 0;
--- a/libinterp/parse-tree/pt-arg-list.h	Mon Mar 11 17:20:34 2013 -0400
+++ b/libinterp/parse-tree/pt-arg-list.h	Mon Mar 11 18:19:10 2013 -0400
@@ -77,6 +77,8 @@
 
   bool all_elements_are_constant (void) const;
 
+  bool is_valid_lvalue_list (void) const;
+
   octave_value_list convert_to_const_vector (const octave_value *object = 0);
 
   std::list<octave_lvalue> lvalue_list (void);