From 7d6ebc0796760e61619bebf4bd8f303c4788f143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Lang=C3=B3?= Date: Fri, 16 Feb 2018 09:12:01 +0100 Subject: [PATCH] Fix assertion in 're_insert_simple_iterator' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is a followup fix after #2169. It also fixes a memory leak. This fixes #2198 and fixes #2204 JerryScript-DCO-1.0-Signed-off-by: László Langó llango.u-szeged@partner.samsung.com --- jerry-core/parser/regexp/re-compiler.c | 47 +++++++++++++---------- jerry-core/parser/regexp/re-parser.c | 12 +++--- tests/jerry/regression-test-issue-2198.js | 17 ++++++++ tests/jerry/regression-test-issue-2204.js | 34 ++++++++++++++++ 4 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 tests/jerry/regression-test-issue-2198.js create mode 100644 tests/jerry/regression-test-issue-2204.js diff --git a/jerry-core/parser/regexp/re-compiler.c b/jerry-core/parser/regexp/re-compiler.c index da318aca51..c4fa8916e3 100644 --- a/jerry-core/parser/regexp/re-compiler.c +++ b/jerry-core/parser/regexp/re-compiler.c @@ -52,8 +52,13 @@ re_append_char_class (void *re_ctx_p, /**< RegExp compiler context */ /** * Insert simple atom iterator + * + * @return empty ecma value - if inserted successfully + * error ecma value - otherwise + * + * Returned value must be freed with ecma_free_value */ -static void +static ecma_value_t re_insert_simple_iterator (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context */ uint32_t new_atom_start_offset) /**< atom start offset */ { @@ -63,7 +68,15 @@ re_insert_simple_iterator (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler con qmin = re_ctx_p->current_token.qmin; qmax = re_ctx_p->current_token.qmax; - JERRY_ASSERT (qmin <= qmax); + + if (qmin == 1 && qmax == 1) + { + return ECMA_VALUE_EMPTY; + } + else if (qmin > qmax) + { + return ecma_raise_syntax_error (ECMA_ERR_MSG ("RegExp quantifier error: qmin > qmax.")); + } /* TODO: optimize bytecode length. Store 0 rather than INF */ @@ -83,6 +96,8 @@ re_insert_simple_iterator (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler con { re_insert_opcode (re_ctx_p->bytecode_ctx_p, offset, RE_OP_NON_GREEDY_ITERATOR); } + + return ECMA_VALUE_EMPTY; } /* re_insert_simple_iterator */ /** @@ -271,10 +286,7 @@ re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context re_append_char (bc_ctx_p, re_canonicalize ((ecma_char_t) re_ctx_p->current_token.value, re_ctx_p->flags & RE_FLAG_IGNORE_CASE)); - if ((re_ctx_p->current_token.qmin != 1) || (re_ctx_p->current_token.qmax != 1)) - { - re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); - } + ret_value = re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); break; } case RE_TOK_PERIOD: @@ -282,10 +294,7 @@ re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context JERRY_TRACE_MSG ("Compile a period\n"); re_append_opcode (bc_ctx_p, RE_OP_PERIOD); - if ((re_ctx_p->current_token.qmin != 1) || (re_ctx_p->current_token.qmax != 1)) - { - re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); - } + ret_value = re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); break; } case RE_TOK_ALTERNATIVE: @@ -387,21 +396,17 @@ re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context : RE_OP_CHAR_CLASS); uint32_t offset = re_get_bytecode_length (re_ctx_p->bytecode_ctx_p); - ECMA_TRY_CATCH (empty_value, - re_parse_char_class (re_ctx_p->parser_ctx_p, - re_append_char_class, - re_ctx_p, - &(re_ctx_p->current_token)), - ret_value); - re_insert_u32 (bc_ctx_p, offset, re_ctx_p->parser_ctx_p->num_of_classes); + ret_value = re_parse_char_class (re_ctx_p->parser_ctx_p, + re_append_char_class, + re_ctx_p, + &(re_ctx_p->current_token)); - if ((re_ctx_p->current_token.qmin != 1) || (re_ctx_p->current_token.qmax != 1)) + if (!ECMA_IS_VALUE_ERROR (ret_value)) { - re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); + re_insert_u32 (bc_ctx_p, offset, re_ctx_p->parser_ctx_p->num_of_classes); + ret_value = re_insert_simple_iterator (re_ctx_p, new_atom_start_offset); } - ECMA_FINALIZE (empty_value); - break; } case RE_TOK_END_GROUP: diff --git a/jerry-core/parser/regexp/re-parser.c b/jerry-core/parser/regexp/re-parser.c index 0af0589e59..b26eba9a22 100644 --- a/jerry-core/parser/regexp/re-parser.c +++ b/jerry-core/parser/regexp/re-parser.c @@ -16,6 +16,7 @@ #include "ecma-exceptions.h" #include "ecma-globals.h" #include "ecma-try-catch-macro.h" +#include "jcontext.h" #include "jrt-libc-includes.h" #include "lit-char-helpers.h" #include "re-compiler.h" @@ -242,11 +243,6 @@ re_parse_iterator (re_parser_ctx_t *parser_ctx_p, /**< RegExp parser context */ JERRY_ASSERT (ecma_is_value_empty (ret_value)); - if (re_token_p->qmin > re_token_p->qmax) - { - ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("RegExp quantifier error: qmin > qmax.")); - } - return ret_value; } /* re_parse_iterator */ @@ -893,11 +889,15 @@ re_parse_next_token (re_parser_ctx_t *parser_ctx_p, /**< RegExp parser context * const lit_utf8_byte_t *input_curr_p = parser_ctx_p->input_curr_p; lit_utf8_decr (&parser_ctx_p->input_curr_p); - if (ecma_is_value_empty (re_parse_iterator (parser_ctx_p, out_token_p))) + ret_value = re_parse_iterator (parser_ctx_p, out_token_p); + if (ecma_is_value_empty (ret_value)) { return ecma_raise_syntax_error (ECMA_ERR_MSG ("Invalid RegExp token.")); } + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (ret_value)); + ecma_free_value (JERRY_CONTEXT (error_value)); + parser_ctx_p->input_curr_p = input_curr_p; out_token_p->type = RE_TOK_CHAR; diff --git a/tests/jerry/regression-test-issue-2198.js b/tests/jerry/regression-test-issue-2198.js new file mode 100644 index 0000000000..06ae33b0d4 --- /dev/null +++ b/tests/jerry/regression-test-issue-2198.js @@ -0,0 +1,17 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// 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. + +var id_0 = Object.prototype.toString ; +Object.prototype.toString = function ( ) { return "SHIFTED" } ; +RegExp ( '#1: __str = new String({}); typeof __str === "object". Actual: typeof __str ==='); diff --git a/tests/jerry/regression-test-issue-2204.js b/tests/jerry/regression-test-issue-2204.js new file mode 100644 index 0000000000..9edd0b3245 --- /dev/null +++ b/tests/jerry/regression-test-issue-2204.js @@ -0,0 +1,34 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// 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. + +try { + new RegExp("\{{91406,456}"); + assert(false); +} catch(e) { + assert(e instanceof SyntaxError) +} + +try { + new RegExp("\{91406,456}"); + assert(false); +} catch(e) { + assert(e instanceof SyntaxError) +} + +try { + new RegExp("\({91406,456}"); + assert(false); +} catch(e) { + assert(e instanceof SyntaxError) +}