changeset 21361:9ca194f7a858

disallow assignment to "end" in indexed assignments (bug #46459) * parse.h, oct-parse.in.yy (octave_base_parser::valid_id_for_assignment): New function. (octave_base_parser::make_assign_op): Use it.
author John W. Eaton <jwe@octave.org>
date Fri, 26 Feb 2016 13:13:21 -0500
parents 06c2a109935c
children 1bb9a34011d1
files libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h
diffstat 2 files changed, 66 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.in.yy	Fri Feb 26 09:19:25 2016 -0800
+++ b/libinterp/parse-tree/oct-parse.in.yy	Fri Feb 26 13:13:21 2016 -0500
@@ -2951,8 +2951,6 @@
 octave_base_parser::make_assign_op (int op, tree_argument_list *lhs,
                                     token *eq_tok, tree_expression *rhs)
 {
-  tree_expression *retval = 0;
-
   octave_value::assign_op t = octave_value::unknown_assign_op;
 
   switch (op)
@@ -3017,25 +3015,65 @@
   int l = eq_tok->line ();
   int c = eq_tok->column ();
 
-  if (lhs->is_simple_assign_lhs ())
+  if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
     {
-      tree_expression *tmp = lhs->remove_front ();
-
-      retval = new tree_simple_assignment (tmp, rhs, false, l, c, t);
+      // Multiple assignments like [x,y] OP= rhs are only valid for
+      // '=', not '+=', etc.
 
       delete lhs;
+      delete rhs;
+
+      bison_error ("computed multiple assignment not allowed", l, c);
+
+      return 0;
     }
-  else if (t == octave_value::op_asn_eq)
-    return new tree_multi_assignment (lhs, rhs, false, l, c);
+
+  if (lhs->is_simple_assign_lhs ())
+    {
+      // We are looking at a simple assignment statement like x = rhs;
+
+      tree_expression *tmp = lhs->remove_front ();
+
+      if ((tmp->is_identifier () || tmp->is_index_expression ())
+          && ! valid_id_for_assignment (tmp->name ()))
+        {
+          std::string kw = tmp->name ();
+
+          delete tmp;
+          delete lhs;
+          delete rhs;
+
+          bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
+
+          return 0;
+        }
+
+      delete lhs;
+
+      return new tree_simple_assignment (tmp, rhs, false, l, c, t);
+    }
   else
     {
-      delete lhs;
-      delete rhs;
-
-      bison_error ("computed multiple assignment not allowed");
+      std::list<std::string> names = lhs->variable_names ();
+
+      for (std::list<std::string>::const_iterator it = names.begin ();
+           it != names.end (); it++)
+        {
+          std::string kw = *it;
+
+          if (! valid_id_for_assignment (kw))
+            {
+              delete lhs;
+              delete rhs;
+
+              bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
+
+              return 0;
+            }
+        }
+
+      return new tree_multi_assignment (lhs, rhs, false, l, c);
     }
-
-  return retval;
 }
 
 // Define a script.
@@ -3986,6 +4024,18 @@
   parse_error_msg = output_buf.str ();
 }
 
+bool
+octave_base_parser::valid_id_for_assignment (const std::string& s)
+{
+  // is_keyword will return true for some identfiers that are only
+  // keywords in certain contexts.
+
+  return (! is_keyword (s)
+          || (! lexer.parsing_classdef
+              && (s == "enumeration" || s == "events"
+                  || s == "methods" || s == "properties")));
+}
+
 int
 octave_parser::run (void)
 {
--- a/libinterp/parse-tree/parse.h	Fri Feb 26 09:19:25 2016 -0800
+++ b/libinterp/parse-tree/parse.h	Fri Feb 26 13:13:21 2016 -0500
@@ -393,6 +393,8 @@
   // Generic error messages.
   void bison_error (const std::string& s, int l = -1, int c = -1);
 
+  bool valid_id_for_assignment (const std::string& s);
+
   // Contains error message if Bison-generated parser returns non-zero
   // status.
   std::string parse_error_msg;