From d650390e474b4659114bc567dc32c5970bbffee6 Mon Sep 17 00:00:00 2001 From: Szilagyi Adam Date: Wed, 15 Dec 2021 12:45:10 +0100 Subject: [PATCH] Fix redeclaration related eval corner cases (#4886) - Fix cases where a function parameter binding is redeclared inside a parameter initializer eval - Fix cases where a let- or function arguments binding is redeclared inside a function block because there is a declaration in a function parameter initializer eval - Also remove the ECMA_PARSE_CHAIN_INDEX_SHIFT macro, added a debugger_eval_chain_index named field to the jerry context instead JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu --- jerry-core/debugger/debugger.c | 3 +- jerry-core/ecma/base/ecma-globals.h | 35 ++---- jerry-core/jcontext/jcontext.h | 1 + jerry-core/parser/js/js-parser-internal.h | 14 +-- jerry-core/parser/js/js-scanner-util.c | 111 ++++++++++++++-- jerry-core/vm/vm.c | 4 +- tests/jerry/es.next/arguments.js | 34 ++++- tests/test262-esnext-excludelist.xml | 147 ---------------------- 8 files changed, 158 insertions(+), 191 deletions(-) diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index 02ee9880e..d7c310c40 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -540,7 +540,8 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s uint32_t chain_index; memcpy (&chain_index, eval_string_p, sizeof (uint32_t)); - uint32_t parse_opts = ECMA_PARSE_DIRECT_EVAL | (chain_index << ECMA_PARSE_CHAIN_INDEX_SHIFT); + uint32_t parse_opts = ECMA_PARSE_DIRECT_EVAL; + JERRY_CONTEXT (debugger_eval_chain_index) = (uint16_t) chain_index; parser_source_char_t source_char; source_char.source_p = eval_string_p + 5; diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 3bd37e403..91bb9c540 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -86,18 +86,8 @@ typedef enum ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */ } ecma_type_t; -#if JERRY_DEBUGGER -/** - * Shift for scope chain index part in ecma_parse_opts - */ -#define ECMA_PARSE_CHAIN_INDEX_SHIFT 16 -#endif /* JERRY_DEBUGGER */ - /** * Option flags for parser_parse_script and internal flags for global_status_flags in parser context. - * Note: - * the last 16 bits is reserved for internal parser flags, because the debugger uses these - * 16 bits to encode the scope chain skip index as well (see ECMA_PARSE_CHAIN_INDEX_SHIFT) */ typedef enum { @@ -112,30 +102,31 @@ typedef enum * See PARSER_SAVE_STATUS_FLAGS / PARSER_RESTORE_STATUS_FLAGS. */ ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */ ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */ - ECMA_PARSE_INSIDE_CLASS_FIELD = (1u << 7), /**< a class field is being parsed */ - ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 8), /**< allow new.target access */ - ECMA_PARSE_FUNCTION_CONTEXT = (1u << 9), /**< function context is present (ECMA_PARSE_DIRECT_EVAL must be set) */ + ECMA_PARSE_FUNCTION_IS_PARSING_ARGS = (1u << 7), /**< set when parsing function arguments */ + ECMA_PARSE_INSIDE_CLASS_FIELD = (1u << 8), /**< a class field is being parsed */ + ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 9), /**< allow new.target access */ + ECMA_PARSE_FUNCTION_CONTEXT = (1u << 10), /**< function context is present (ECMA_PARSE_DIRECT_EVAL must be set) */ - ECMA_PARSE_HAS_SOURCE_VALUE = (1u << 10), /**< source_p points to a value list + ECMA_PARSE_HAS_SOURCE_VALUE = (1u << 11), /**< source_p points to a value list * and the first value is the source code */ - ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE = (1u << 11), /**< source_p points to a value list + ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE = (1u << 12), /**< source_p points to a value list * and the second value is the argument list */ #if JERRY_ESNEXT - ECMA_PARSE_GENERATOR_FUNCTION = (1u << 12), /**< generator function is parsed */ - ECMA_PARSE_ASYNC_FUNCTION = (1u << 13), /**< async function is parsed */ + ECMA_PARSE_GENERATOR_FUNCTION = (1u << 13), /**< generator function is parsed */ + ECMA_PARSE_ASYNC_FUNCTION = (1u << 14), /**< async function is parsed */ #endif /* JERRY_ESNEXT */ /* These flags are internally used by the parser. */ - ECMA_PARSE_INTERNAL_FREE_SOURCE = (1u << 14), /**< free source_p data */ - ECMA_PARSE_INTERNAL_FREE_ARG_LIST = (1u << 15), /**< free arg_list_p data */ + ECMA_PARSE_INTERNAL_FREE_SOURCE = (1u << 15), /**< free source_p data */ + ECMA_PARSE_INTERNAL_FREE_ARG_LIST = (1u << 16), /**< free arg_list_p data */ #if JERRY_ESNEXT - ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 16), /**< the parser is in pre-scanning mode */ + ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 17), /**< the parser is in pre-scanning mode */ #endif /* JERRY_ESNEXT */ #if JERRY_MODULE_SYSTEM - ECMA_PARSE_INTERNAL_HAS_IMPORT_META = (1u << 17), /**< module has import.meta expression */ + ECMA_PARSE_INTERNAL_HAS_IMPORT_META = (1u << 18), /**< module has import.meta expression */ #endif /* JERRY_MODULE_SYSTEM */ #if JERRY_FUNCTION_TO_STRING - ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 18), /**< source has 4 byte marker */ + ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 19), /**< source has 4 byte marker */ #endif /* JERRY_FUNCTION_TO_STRING */ #ifndef JERRY_NDEBUG /** diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index a4854514b..e7a1ae891 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -236,6 +236,7 @@ struct jerry_context_t jmem_cpointer_t debugger_byte_code_free_tail; /**< tail of byte code free linked list */ uint32_t debugger_flags; /**< debugger flags */ uint16_t debugger_received_length; /**< length of currently received bytes */ + uint16_t debugger_eval_chain_index; /**< eval chain index */ uint8_t debugger_message_delay; /**< call receive message when reaches zero */ uint8_t debugger_max_send_size; /**< maximum amount of data that can be sent */ uint8_t debugger_max_receive_size; /**< maximum amount of data that can be received */ diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 1043878e0..c61692f61 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -64,15 +64,15 @@ typedef enum PARSER_IS_GENERATOR_FUNCTION = (1u << 14), /**< a generator function is parsed */ PARSER_IS_ASYNC_FUNCTION = (1u << 15), /**< an async function is parsed */ PARSER_DISALLOW_AWAIT_YIELD = (1u << 16), /**< throw SyntaxError for await / yield keywords */ - PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 17), /**< set when parsing function arguments */ - PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1u << 18), /**< function has complex (ES2015+) argument definition */ - PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */ - PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed + PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT = (1u << 17), /**< function has complex (ES2015+) argument definition */ + PARSER_FUNCTION_HAS_REST_PARAM = (1u << 18), /**< function has rest parameter */ + PARSER_CLASS_CONSTRUCTOR = (1u << 19), /**< a class constructor is parsed * Note: PARSER_ALLOW_SUPER must be present */ - /* These four status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ - PARSER_ALLOW_SUPER = (1u << 21), /**< allow super property access */ - PARSER_ALLOW_SUPER_CALL = (1u << 22), /**< allow super constructor call + /* These five status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ + PARSER_ALLOW_SUPER = (1u << 20), /**< allow super property access */ + PARSER_ALLOW_SUPER_CALL = (1u << 21), /**< allow super constructor call * Note: PARSER_CLASS_CONSTRUCTOR must be present */ + PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 22), /**< set when parsing function arguments */ PARSER_INSIDE_CLASS_FIELD = (1u << 23), /**< a class field is being parsed */ PARSER_ALLOW_NEW_TARGET = (1u << 24), /**< allow new.target parsing in the current context */ PARSER_IS_METHOD = (1u << 25), /**< method is parsed */ diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c index 29aa6fcce..a3ecfbf0c 100644 --- a/jerry-core/parser/js/js-scanner-util.c +++ b/jerry-core/parser/js/js-scanner-util.c @@ -400,8 +400,107 @@ scanner_seek (parser_context_t *context_p) /**< context */ context_p->next_scanner_info_p = prev_p->next_p; } /* scanner_seek */ +/** + * Checks whether a literal is equal to "arguments". + */ +static inline bool JERRY_ATTR_ALWAYS_INLINE +scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */ +{ + return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9); +} /* scanner_literal_is_arguments */ + #if JERRY_ESNEXT +/** + * Find if there is a duplicated argument in the given context + * + * @return true - if there are duplicates, false - otherwise + */ +static bool +scanner_find_duplicated_arg (parser_context_t *context_p, lexer_lit_location_t *lit_loc_p) +{ + if (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)) + { + return false; + } + + if (scanner_literal_is_arguments (lit_loc_p)) + { + return true; + } + + uint16_t register_end, encoding_limit, encoding_delta; + ecma_value_t *literal_p; + ecma_value_t *literal_start_p; + + const ecma_compiled_code_t *bytecode_header_p = JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + + register_end = args_p->register_end; + + literal_p = (ecma_value_t *) (args_p + 1); + literal_p -= register_end; + literal_start_p = literal_p; + literal_p += args_p->literal_end; + } + + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) + { + encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA; + } + else + { + encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT; + encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA; + } + + uint8_t *byte_code_p = (uint8_t *) literal_p; + + bool found_duplicate = false; + + while (*byte_code_p == CBC_CREATE_LOCAL) + { + byte_code_p++; + uint16_t literal_index = *byte_code_p++; + + if (literal_index >= encoding_limit) + { + literal_index = (uint16_t) (((literal_index << 8) | *byte_code_p++) - encoding_delta); + } + + ecma_string_t *arg_string = ecma_get_string_from_value (literal_start_p[literal_index]); + uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, lit_loc_p->length); + lexer_convert_ident_to_cesu8 (destination_p, lit_loc_p->char_p, lit_loc_p->length); + ecma_string_t *search_key_p = ecma_new_ecma_string_from_utf8 (destination_p, lit_loc_p->length); + scanner_free (destination_p, lit_loc_p->length); + + found_duplicate = ecma_compare_ecma_strings (arg_string, search_key_p); + ecma_deref_ecma_string (search_key_p); + + if (found_duplicate) + { + break; + } + } + + return found_duplicate; +} /* scanner_find_duplicated_arg */ + /** * Find any let/const declaration of a given literal. * @@ -466,7 +565,8 @@ scanner_scope_find_lexical_declaration (parser_context_t *context_p, /**< contex { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); - if (property_p != NULL && ecma_is_property_enumerable (*property_p)) + if (property_p != NULL + && (ecma_is_property_enumerable (*property_p) || scanner_find_duplicated_arg (context_p, literal_p))) { ecma_deref_ecma_string (name_p); return true; @@ -549,15 +649,6 @@ scanner_push_literal_pool (parser_context_t *context_p, /**< context */ JERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX, maximum_ident_length_must_fit_in_a_byte); -/** - * Checks whether a literal is equal to "arguments". - */ -static inline bool JERRY_ATTR_ALWAYS_INLINE -scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */ -{ - return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9); -} /* scanner_literal_is_arguments */ - /** * Current status of arguments. */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 883043904..7c3eaafd4 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -315,8 +315,8 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p; #if JERRY_DEBUGGER - uint32_t chain_index = parse_opts >> ECMA_PARSE_CHAIN_INDEX_SHIFT; - parse_opts &= (1 << ECMA_PARSE_CHAIN_INDEX_SHIFT) - 1; + uint32_t chain_index = JERRY_CONTEXT (debugger_eval_chain_index); + JERRY_CONTEXT (debugger_eval_chain_index) = 0; while (chain_index != 0) { diff --git a/tests/jerry/es.next/arguments.js b/tests/jerry/es.next/arguments.js index a6fef6a1e..5031f4621 100644 --- a/tests/jerry/es.next/arguments.js +++ b/tests/jerry/es.next/arguments.js @@ -218,7 +218,37 @@ function f22 (arguments, [a = arguments]) { } f22(3.1, []); -function f23(arguments, eval = () => eval()) { +try { + function f23(p = eval("var arguments"), arguments) + { + } + f23() + assert(false) +} catch (e) { + assert(e instanceof SyntaxError) +} + +try { + function f24(p = eval("var arguments")) { + let arguments; + } + f24() + assert(false) +} catch (e) { + assert(e instanceof SyntaxError) +} + +try { + function f25(p = eval("var arguments")) { + function arguments() { } + } + f25() + assert(false) +} catch (e) { + assert(e instanceof SyntaxError) +} + +function f26(arguments, eval = () => eval()) { assert(arguments === undefined); } -f23(undefined); +f26(undefined); diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index e24a28d73..a6766b08d 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -79,142 +79,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -228,7 +92,6 @@ - @@ -267,14 +130,10 @@ - - - - @@ -572,8 +431,6 @@ - - @@ -3870,8 +3727,6 @@ - - @@ -3919,7 +3774,6 @@ - @@ -3935,7 +3789,6 @@ -