Mercurial > octave
changeset 27728:5e92bff668d6
disallow lvalue references in anonymous functions (bug #57255)
* libinterp/parse-tree/anon-fcn-validator.h,
libinterp/parse-tree/anon-fcn-validator.cc: New files.
* module.mk: Update.
* oct-parse.yy (anon_fcn_handle): Abort parse if make_anon_fcn_handle
returns invalid object.
(base_parser::make_anon_fcn_handle): Use new anon_fcn_validator class
to check anonymous function. Set parser error and return nullptr if
validation fails.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 20 Nov 2019 19:22:54 -0600 |
parents | b8684580dd23 |
children | 718845eb3c7a |
files | libinterp/parse-tree/anon-fcn-validator.cc libinterp/parse-tree/anon-fcn-validator.h libinterp/parse-tree/module.mk libinterp/parse-tree/oct-parse.yy |
diffstat | 4 files changed, 184 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/anon-fcn-validator.cc Wed Nov 20 19:22:54 2019 -0600 @@ -0,0 +1,80 @@ +/* + +Copyright (C) 2019 John W. Eaton + +This file is part of Octave. + +Octave is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<https://www.gnu.org/licenses/>. + +*/ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include <string> + +#include "anon-fcn-validator.h" +#include "ov.h" +#include "pt-all.h" + +namespace octave +{ + anon_fcn_validator::anon_fcn_validator (tree_parameter_list *, + tree_expression *expr) + : m_ok (true), m_line (-1), m_column (-1), m_message () + { + expr->accept (*this); + } + + void anon_fcn_validator::visit_postfix_expression (tree_postfix_expression& expr) + { + octave_value::unary_op op = expr.op_type (); + + if (op == octave_value::op_incr || op == octave_value::op_decr) + error (expr); + else + tree_walker::visit_postfix_expression (expr); + } + + void anon_fcn_validator::visit_prefix_expression (tree_prefix_expression& expr) + { + octave_value::unary_op op = expr.op_type (); + + if (op == octave_value::op_incr || op == octave_value::op_decr) + error (expr); + else + tree_walker::visit_prefix_expression (expr); + } + + void anon_fcn_validator::visit_multi_assignment (tree_multi_assignment& expr) + { + error (expr); + } + + void anon_fcn_validator::visit_simple_assignment (tree_simple_assignment& expr) + { + error (expr); + } + + void anon_fcn_validator::error (tree_expression& expr) + { + m_ok = false; + m_line = expr.line (); + m_column = expr.column (); + m_message + = "invalid use of operator " + expr.oper () + " in anonymous function"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/anon-fcn-validator.h Wed Nov 20 19:22:54 2019 -0600 @@ -0,0 +1,79 @@ +/* + +Copyright (C) 2019 John W. Eaton + +This file is part of Octave. + +Octave is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<https://www.gnu.org/licenses/>. + +*/ + +#if ! defined (octave_anon_fcn_validator_h) +#define octave_anon_fcn_validator_h 1 + +#include "octave-config.h" + +#include <string> + +#include "pt-walk.h" + +namespace octave +{ + class tree_expression; + class tree_parameter_list; + + // How to check the semantics of the code that the parse trees represent. + + class anon_fcn_validator : public tree_walker + { + public: + + anon_fcn_validator (tree_parameter_list *, tree_expression *expr); + + // No copying! + + anon_fcn_validator (const anon_fcn_validator&) = delete; + + anon_fcn_validator& operator = (const anon_fcn_validator&) = delete; + + ~anon_fcn_validator (void) = default; + + void visit_postfix_expression (tree_postfix_expression&); + + void visit_prefix_expression (tree_prefix_expression&); + + void visit_multi_assignment (tree_multi_assignment&); + + void visit_simple_assignment (tree_simple_assignment&); + + bool ok (void) const { return m_ok; } + + int line (void) const { return m_line; } + int column (void) const { return m_column; } + + std::string message (void) const { return m_message; } + + private: + + bool m_ok; + int m_line; + int m_column; + std::string m_message; + + void error (tree_expression& expr); + }; +} + +#endif
--- a/libinterp/parse-tree/module.mk Wed Nov 20 17:22:01 2019 -0800 +++ b/libinterp/parse-tree/module.mk Wed Nov 20 19:22:54 2019 -0600 @@ -1,4 +1,5 @@ PARSE_TREE_INC = \ + %reldir%/anon-fcn-validator.h \ %reldir%/bp-table.h \ %reldir%/comment-list.h \ %reldir%/jit-ir.h \ @@ -48,6 +49,7 @@ ## be distributed but not installed. PARSE_TREE_SRC = \ + %reldir%/anon-fcn-validator.cc \ %reldir%/bp-table.cc \ %reldir%/comment-list.cc \ %reldir%/jit-ir.cc \
--- a/libinterp/parse-tree/oct-parse.yy Wed Nov 20 17:22:01 2019 -0800 +++ b/libinterp/parse-tree/oct-parse.yy Wed Nov 20 19:22:54 2019 -0600 @@ -53,6 +53,7 @@ #include "quit.h" #include "Cell.h" +#include "anon-fcn-validator.h" #include "builtin-defun-decls.h" #include "defun.h" #include "dynamic-ld.h" @@ -606,6 +607,11 @@ anon_fcn_handle : '@' param_list stmt_begin expr_no_assign { $$ = parser.make_anon_fcn_handle ($2, $4); + if (! $$) + { + // make_anon_fcn_handle deleted $2 and $4. + YYABORT; + } lexer.m_nesting_level.remove (); } | '@' param_list stmt_begin error @@ -2393,6 +2399,23 @@ int l = m_lexer.m_input_line_number; int c = m_lexer.m_current_input_column; + // FIXME: We need to examine EXPR and issue an error if any + // sub-expression contains an assignment, compound assignment, + // increment, or decrement operator. + + anon_fcn_validator validator (param_list, expr); + + if (! validator.ok ()) + { + delete param_list; + delete expr; + + bison_error (validator.message (), validator.line (), + validator.column ()); + + return nullptr; + } + symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope (); symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();