Skip to content

Commit

Permalink
Raise syntax error on invalid unicode escape sequences
Browse files Browse the repository at this point in the history
Instead of failing with an assertion

The parser context was required for raising the error, which had to be
added to all functions that can call `lexer_unchecked_hex_to_character`.

JerryScript-DCO-1.0-Signed-off-by: Máté Tokodi mate.tokodi@szteszoftver.hu
  • Loading branch information
matetokodi committed Jun 24, 2024
1 parent 2dbb6f7 commit 55868f3
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 38 deletions.
50 changes: 31 additions & 19 deletions jerry-core/parser/js/js-lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ lexer_hex_in_braces_to_code_point (const uint8_t *source_p, /**< current source
* @return character value
*/
static lit_code_point_t
lexer_unchecked_hex_to_character (const uint8_t **source_p) /**< [in, out] current source position */
lexer_unchecked_hex_to_character (parser_context_t *context_p, /**< context */
const uint8_t **source_p) /**< [in, out] current source position */
{
lit_code_point_t result = 0;
const uint8_t *char_p = *source_p;
Expand All @@ -174,13 +175,19 @@ lexer_unchecked_hex_to_character (const uint8_t **source_p) /**< [in, out] curre
}
else
{
JERRY_ASSERT ((byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F)
|| (byte >= LIT_CHAR_UPPERCASE_A && byte <= LIT_CHAR_UPPERCASE_F));
if (!((byte >= LIT_CHAR_LOWERCASE_A && byte <= LIT_CHAR_LOWERCASE_F)
|| (byte >= LIT_CHAR_UPPERCASE_A && byte <= LIT_CHAR_UPPERCASE_F)))
{
parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE);
}

result += LEXER_TO_ASCII_LOWERCASE (byte) - (LIT_CHAR_LOWERCASE_A - 10);
}

JERRY_ASSERT (result <= LIT_UNICODE_CODE_POINT_MAX);
if (result > LIT_UNICODE_CODE_POINT_MAX)
{
parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE);
}

if (length == 0)
{
Expand Down Expand Up @@ -713,7 +720,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */

if (JERRY_UNLIKELY (context_p->token.lit_location.status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))
{
lexer_convert_ident_to_cesu8 (buffer_p, ident_start_p, (prop_length_t) length);
lexer_convert_ident_to_cesu8 (context_p, buffer_p, ident_start_p, (prop_length_t) length);
ident_start_p = buffer_p;
}

Expand Down Expand Up @@ -2070,7 +2077,8 @@ lexer_scan_private_identifier (parser_context_t *context_p) /**< context */
* Convert an ident with escapes to a utf8 string.
*/
void
lexer_convert_ident_to_cesu8 (uint8_t *destination_p, /**< destination string */
lexer_convert_ident_to_cesu8 (parser_context_t *context_p, /**< context */
uint8_t *destination_p, /**< destination string */
const uint8_t *source_p, /**< source string */
prop_length_t length) /**< length of destination string */
{
Expand All @@ -2083,7 +2091,8 @@ lexer_convert_ident_to_cesu8 (uint8_t *destination_p, /**< destination string */
if (*source_p == LIT_CHAR_BACKSLASH)
{
source_p += 2;
destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p));
destination_p +=
lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (context_p, &source_p));
continue;
}

Expand Down Expand Up @@ -2130,7 +2139,7 @@ lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */

if (literal_p->type == LEXER_IDENT_LITERAL)
{
lexer_convert_ident_to_cesu8 (destination_start_p, literal_p->char_p, literal_p->length);
lexer_convert_ident_to_cesu8 (context_p, destination_start_p, literal_p->char_p, literal_p->length);
return destination_start_p;
}

Expand Down Expand Up @@ -2229,7 +2238,8 @@ lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */
if (*source_p == LIT_CHAR_LOWERCASE_X || *source_p == LIT_CHAR_LOWERCASE_U)
{
source_p++;
destination_p += lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (&source_p));
destination_p +=
lit_code_point_to_cesu8_bytes (destination_p, lexer_unchecked_hex_to_character (context_p, &source_p));
continue;
}

Expand Down Expand Up @@ -3286,7 +3296,8 @@ lexer_check_property_modifier (parser_context_t *context_p) /**< context */
* @return true if the two identifiers are the same
*/
static bool
lexer_compare_identifier_to_chars (const uint8_t *left_p, /**< left identifier */
lexer_compare_identifier_to_chars (parser_context_t *context_p, /**< context */
const uint8_t *left_p, /**< left identifier */
const uint8_t *right_p, /**< right identifier string */
size_t size) /**< byte size of the two identifiers */
{
Expand All @@ -3307,7 +3318,7 @@ lexer_compare_identifier_to_chars (const uint8_t *left_p, /**< left identifier *
if (*left_p == LIT_CHAR_BACKSLASH)
{
left_p += 2;
lit_code_point_t code_point = lexer_unchecked_hex_to_character (&left_p);
lit_code_point_t code_point = lexer_unchecked_hex_to_character (context_p, &left_p);

escape_size = lit_code_point_to_cesu8_bytes (utf8_buf, code_point);
}
Expand Down Expand Up @@ -3346,7 +3357,8 @@ lexer_compare_identifier_to_chars (const uint8_t *left_p, /**< left identifier *
* @return true if the identifier equals to string
*/
bool
lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, /**< left literal */
lexer_compare_identifier_to_string (parser_context_t *context_p, /**< context */
const lexer_lit_location_t *left_p, /**< left literal */
const uint8_t *right_p, /**< right identifier string */
size_t size) /**< byte size of the right identifier */
{
Expand All @@ -3360,7 +3372,7 @@ lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, /**< lef
return memcmp (left_p->char_p, right_p, size) == 0;
}

return lexer_compare_identifier_to_chars (left_p->char_p, right_p, size);
return lexer_compare_identifier_to_chars (context_p, left_p->char_p, right_p, size);
} /* lexer_compare_identifier_to_string */

/**
Expand All @@ -3385,25 +3397,25 @@ lexer_compare_identifiers (parser_context_t *context_p, /**< context */

if (!(left_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))
{
return lexer_compare_identifier_to_chars (right_p->char_p, left_p->char_p, length);
return lexer_compare_identifier_to_chars (context_p, right_p->char_p, left_p->char_p, length);
}

if (!(right_p->status_flags & LEXER_LIT_LOCATION_HAS_ESCAPE))
{
return lexer_compare_identifier_to_chars (left_p->char_p, right_p->char_p, length);
return lexer_compare_identifier_to_chars (context_p, left_p->char_p, right_p->char_p, length);
}

if (length <= 64)
{
uint8_t buf_p[64];
lexer_convert_ident_to_cesu8 (buf_p, left_p->char_p, length);
return lexer_compare_identifier_to_chars (right_p->char_p, buf_p, length);
lexer_convert_ident_to_cesu8 (context_p, buf_p, left_p->char_p, length);
return lexer_compare_identifier_to_chars (context_p, right_p->char_p, buf_p, length);
}

uint8_t *dynamic_buf_p = parser_malloc (context_p, length);

lexer_convert_ident_to_cesu8 (dynamic_buf_p, left_p->char_p, length);
bool result = lexer_compare_identifier_to_chars (right_p->char_p, dynamic_buf_p, length);
lexer_convert_ident_to_cesu8 (context_p, dynamic_buf_p, left_p->char_p, length);
bool result = lexer_compare_identifier_to_chars (context_p, right_p->char_p, dynamic_buf_p, length);
parser_free (dynamic_buf_p, length);

return result;
Expand Down
9 changes: 6 additions & 3 deletions jerry-core/parser/js/js-parser-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,10 @@ parser_parse_class_body (parser_context_t *context_p, /**< context */
else if (is_static && !is_private)
{
if (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
&& lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9))
&& lexer_compare_identifier_to_string (context_p,
&context_p->token.lit_location,
(uint8_t *) "prototype",
9))
{
parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE);
}
Expand Down Expand Up @@ -742,7 +745,7 @@ parser_parse_class_body (parser_context_t *context_p, /**< context */
{
if (is_static && !is_private)
{
if (lexer_compare_identifier_to_string (&context_p->token.lit_location, (uint8_t *) "prototype", 9))
if (lexer_compare_identifier_to_string (context_p, &context_p->token.lit_location, (uint8_t *) "prototype", 9))
{
parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE);
}
Expand Down Expand Up @@ -1444,7 +1447,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
const lexer_lit_location_t *literal_p = (const lexer_lit_location_t *) context_p->lit_object.literal_p;
bool is_proto = ((context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL)
&& lexer_compare_identifier_to_string (literal_p, (uint8_t *) "__proto__", 9)
&& lexer_compare_identifier_to_string (context_p, literal_p, (uint8_t *) "__proto__", 9)
&& lexer_check_next_character (context_p, LIT_CHAR_COLON));
if (is_proto)
{
Expand Down
10 changes: 8 additions & 2 deletions jerry-core/parser/js/js-parser-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,10 @@ void lexer_parse_string (parser_context_t *context_p, lexer_string_options_t opt
void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type);
bool lexer_scan_identifier (parser_context_t *context_p, lexer_parse_options_t opts);
void lexer_check_property_modifier (parser_context_t *context_p);
void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source_p, prop_length_t length);
void lexer_convert_ident_to_cesu8 (parser_context_t *context_p,
uint8_t *destination_p,
const uint8_t *source_p,
prop_length_t length);

const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p,
const lexer_lit_location_t *literal_p,
Expand All @@ -764,7 +767,10 @@ void lexer_convert_push_number_to_push_literal (parser_context_t *context_p);
uint16_t lexer_construct_function_object (parser_context_t *context_p, uint32_t extra_status_flags);
uint16_t lexer_construct_class_static_block_function (parser_context_t *context_p);
void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only);
bool lexer_compare_identifier_to_string (const lexer_lit_location_t *left_p, const uint8_t *right_p, size_t size);
bool lexer_compare_identifier_to_string (parser_context_t *context_p,
const lexer_lit_location_t *left_p,
const uint8_t *right_p,
size_t size);
bool lexer_compare_identifiers (parser_context_t *context_p,
const lexer_lit_location_t *left_p,
const lexer_lit_location_t *right_p);
Expand Down
3 changes: 2 additions & 1 deletion jerry-core/parser/js/js-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,8 @@ parser_resolve_private_identifier_eval (parser_context_t *context_p) /**< contex
ecma_string_t *search_key_p;
uint8_t *destination_p = (uint8_t *) parser_malloc (context_p, context_p->token.lit_location.length);

lexer_convert_ident_to_cesu8 (destination_p,
lexer_convert_ident_to_cesu8 (context_p,
destination_p,
context_p->token.lit_location.char_p,
context_p->token.lit_location.length);

Expand Down
23 changes: 12 additions & 11 deletions jerry-core/parser/js/js-scanner-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,10 @@ scanner_seek (parser_context_t *context_p) /**< context */
* 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 */
scanner_literal_is_arguments (parser_context_t *context_p, /**< context */
lexer_lit_location_t *literal_p) /**< literal */
{
return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9);
return lexer_compare_identifier_to_string (context_p, literal_p, (const uint8_t *) "arguments", 9);
} /* scanner_literal_is_arguments */

/**
Expand All @@ -408,7 +409,7 @@ scanner_find_duplicated_arg (parser_context_t *context_p, lexer_lit_location_t *
return false;
}

if (scanner_literal_is_arguments (lit_loc_p))
if (scanner_literal_is_arguments (context_p, lit_loc_p))
{
return true;
}
Expand Down Expand Up @@ -469,7 +470,7 @@ scanner_find_duplicated_arg (parser_context_t *context_p, lexer_lit_location_t *

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);
lexer_convert_ident_to_cesu8 (context_p, 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);

Expand Down Expand Up @@ -510,7 +511,7 @@ scanner_scope_find_lexical_declaration (parser_context_t *context_p, /**< contex
{
uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);

lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
lexer_convert_ident_to_cesu8 (context_p, destination_p, literal_p->char_p, literal_p->length);

name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);

Expand Down Expand Up @@ -728,7 +729,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
continue;
}

if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p))
if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (context_p, literal_p))
{
JERRY_ASSERT (arguments_type != SCANNER_ARGUMENTS_NOT_PRESENT);
status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
Expand Down Expand Up @@ -1307,7 +1308,7 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
literal_p->type = type;
}

if (has_arguments && scanner_literal_is_arguments (literal_p))
if (has_arguments && scanner_literal_is_arguments (context_p, literal_p))
{
has_arguments = false;
}
Expand All @@ -1332,7 +1333,7 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
*new_literal_p = *literal_p;
}
else if (has_arguments && scanner_literal_is_arguments (literal_p))
else if (has_arguments && scanner_literal_is_arguments (context_p, literal_p))
{
/* Arguments object is directly referenced from the function arguments */
new_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_IN_ARGS;
Expand Down Expand Up @@ -1412,7 +1413,7 @@ scanner_add_custom_literal (parser_context_t *context_p, /**< context */
return literal_p;
}
}
else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
else if (lexer_compare_identifier_to_string (context_p, literal_p, char_p, length))
{
/* The non-escaped version is preferred. */
literal_p->char_p = char_p;
Expand Down Expand Up @@ -1517,7 +1518,7 @@ scanner_append_argument (parser_context_t *context_p, /**< context */
break;
}
}
else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
else if (lexer_compare_identifier_to_string (context_p, literal_p, char_p, length))
{
break;
}
Expand Down Expand Up @@ -1660,7 +1661,7 @@ scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
return;
}
}
else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
else if (lexer_compare_identifier_to_string (context_p, literal_p, char_p, length))
{
scanner_raise_redeclaration_error (context_p);
return;
Expand Down
15 changes: 15 additions & 0 deletions tests/jerry/fail/regression-test-issue-5134.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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.

import{a as "\{{12,34}"
4 changes: 2 additions & 2 deletions tools/cppcheck/suppressions-list
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ knownConditionTrueFalse:jerry-core/*.c
knownConditionTrueFalse:jerry-math/*.c
negativeIndex:jerry-core/*.c
nullPointerArithmetic:jerry-core/parser/js/js-parser-line-info-create.c:572
nullPointerArithmetic:jerry-core/parser/js/js-scanner-util.c:2345
nullPointerArithmetic:jerry-core/parser/js/js-scanner-util.c:2346
nullPointerArithmeticRedundantCheck:jerry-core/*.c
nullPointerRedundantCheck:jerry-core/*.c
nullPointerRedundantCheck:jerry-ext/*.c
Expand All @@ -31,7 +31,7 @@ shiftNegativeLHS:jerry-math/*.c
shiftTooManyBits:jerry-core/*.c
shiftTooManyBitsSigned:jerry-math/*.c
signConversionCond:jerry-core/*.c
uninitvar:jerry-core/parser/js/js-parser-expr.c:3423
uninitvar:jerry-core/parser/js/js-parser-expr.c:3426
uninitvar:tests/unit-core/test-api-objecttype.c:119
unmatchedSuppression:jerry-core/*.inc.h
unreadVariable:jerry-core/*.c
Expand Down

0 comments on commit 55868f3

Please sign in to comment.