From 94cb6aec26c21b608e54b8e6efd854943a21ba1b Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Wed, 21 Oct 2015 13:25:37 +0900 Subject: [PATCH] Fix prop_getters stack manipulation for assignment expression. Related issue: #614 JerryScript-DCO-1.0-Signed-off-by: Ilyong Cho ily.cho@samsung.com --- jerry-core/parser/js/opcodes-dumper.cpp | 77 +++++++++++++++--------- jerry-core/parser/js/opcodes-dumper.h | 2 +- jerry-core/parser/js/parser.cpp | 3 +- tests/jerry/regression-test-issue-614.js | 26 ++++++++ 4 files changed, 78 insertions(+), 30 deletions(-) create mode 100644 tests/jerry/regression-test-issue-614.js diff --git a/jerry-core/parser/js/opcodes-dumper.cpp b/jerry-core/parser/js/opcodes-dumper.cpp index 567047718..b6cef8dda 100644 --- a/jerry-core/parser/js/opcodes-dumper.cpp +++ b/jerry-core/parser/js/opcodes-dumper.cpp @@ -628,25 +628,23 @@ dump_prop_setter_or_triple_address_res (vm_op_t opcode, jsp_operand_t res, jsp_operand_t op) { - const op_meta last = STACK_TOP (prop_getters); - if (last.op.op_idx == VM_OP_PROP_GETTER) + if (res.is_register_operand ()) { + /* + * Left-hand-side must be a member expression and corresponding prop_getter + * op is on top of the stack. + */ + const op_meta last = STACK_TOP (prop_getters); + JERRY_ASSERT (last.op.op_idx == VM_OP_PROP_GETTER); + res = dump_triple_address_and_prop_setter_res (opcode, last, op); + + STACK_DROP (prop_getters, 1); } else { - if (res.is_register_operand ()) - { - /* - * FIXME: - * Implement correct handling of references through parser operands - */ - PARSE_ERROR (JSP_EARLY_ERROR_REFERENCE, "Invalid left-hand-side expression", LIT_ITERATOR_POS_ZERO); - } - dump_triple_address (opcode, res, res, op); } - STACK_DROP (prop_getters, 1); return res; } @@ -1865,37 +1863,60 @@ rewrite_jump_to_end (void) } void -start_dumping_assignment_expression (void) +start_dumping_assignment_expression (jsp_operand_t lhs, locus loc __attr_unused___) { - const op_meta last = last_dumped_op_meta (); - if (last.op.op_idx == VM_OP_PROP_GETTER) + if (lhs.is_register_operand ()) { - serializer_set_writing_position ((vm_instr_counter_t) (serializer_get_current_instr_counter () - 1)); + /* + * Having left-handside of assignment expression as a temporary register + * means it's either a member expression or something else. Under the condition, + * only member expression could be a L-value for assignment expression, otherwise + * it's an invalid lhs expression. + */ + + const op_meta last = last_dumped_op_meta (); + + if (last.op.op_idx == VM_OP_PROP_GETTER) + { + /* + * If lhs is a member expression, last dumped op code should be + * prop_getter. For we are going to use the expression as L-value, it will + * be a prop_setter later, save the op to stack. + */ + serializer_set_writing_position ((vm_instr_counter_t) (serializer_get_current_instr_counter () - 1)); + STACK_PUSH (prop_getters, last); + } + else + { + /* + * If lhs is a temporary register operand but not a member expression, It + * is an invalid left-hand-side expression. + */ + PARSE_ERROR (JSP_EARLY_ERROR_REFERENCE, "Invalid left-hand-side expression", loc); + } } - STACK_PUSH (prop_getters, last); } jsp_operand_t dump_prop_setter_or_variable_assignment_res (jsp_operand_t res, jsp_operand_t op) { - const op_meta last = STACK_TOP (prop_getters); - if (last.op.op_idx == VM_OP_PROP_GETTER) + if (res.is_register_operand ()) { + /* + * Left-hand-side must be a member expression and corresponding prop_getter + * op is on top of the stack. + */ + const op_meta last = STACK_TOP (prop_getters); + JERRY_ASSERT (last.op.op_idx == VM_OP_PROP_GETTER); + dump_prop_setter_op_meta (last, op); + + STACK_DROP (prop_getters, 1); } else { - if (res.is_register_operand ()) - { - /* - * FIXME: - * Implement correct handling of references through parser operands - */ - PARSE_ERROR (JSP_EARLY_ERROR_REFERENCE, "Invalid left-hand-side expression", LIT_ITERATOR_POS_ZERO); - } dump_variable_assignment (res, op); } - STACK_DROP (prop_getters, 1); return op; } diff --git a/jerry-core/parser/js/opcodes-dumper.h b/jerry-core/parser/js/opcodes-dumper.h index 6ce9eb41b..87bea9ef0 100644 --- a/jerry-core/parser/js/opcodes-dumper.h +++ b/jerry-core/parser/js/opcodes-dumper.h @@ -425,7 +425,7 @@ void rewrite_conditional_check (void); void dump_jump_to_end_for_rewrite (void); void rewrite_jump_to_end (void); -void start_dumping_assignment_expression (void); +void start_dumping_assignment_expression (jsp_operand_t, locus); jsp_operand_t dump_prop_setter_or_variable_assignment_res (jsp_operand_t, jsp_operand_t); jsp_operand_t dump_prop_setter_or_addition_res (jsp_operand_t, jsp_operand_t); jsp_operand_t dump_prop_setter_or_multiplication_res (jsp_operand_t, jsp_operand_t); diff --git a/jerry-core/parser/js/parser.cpp b/jerry-core/parser/js/parser.cpp index 64f06e469..ffb19965b 100644 --- a/jerry-core/parser/js/parser.cpp +++ b/jerry-core/parser/js/parser.cpp @@ -1730,6 +1730,7 @@ static jsp_operand_t parse_assignment_expression (bool in_allowed) { bool is_conditional = false; + locus loc_expr = tok.loc; jsp_operand_t expr = parse_conditional_expression (in_allowed, &is_conditional); if (is_conditional) { @@ -1755,7 +1756,7 @@ parse_assignment_expression (bool in_allowed) { jsp_early_error_check_for_eval_and_arguments_in_strict_mode (expr, is_strict_mode (), tok.loc); skip_newlines (); - start_dumping_assignment_expression (); + start_dumping_assignment_expression (expr, loc_expr); const jsp_operand_t assign_expr = parse_assignment_expression (in_allowed); if (tt == TOK_EQ) diff --git a/tests/jerry/regression-test-issue-614.js b/tests/jerry/regression-test-issue-614.js new file mode 100644 index 000000000..fd855ffe0 --- /dev/null +++ b/tests/jerry/regression-test-issue-614.js @@ -0,0 +1,26 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +JSON.stringify & (Date = 1); + +b = 1; +this.a = 2; +this.a +b = 3; +assert(b == 3); +assert(a == 2); +this.a & (b = 4); +assert(b == 4); +assert(a == 2);