Skip to content

Improve expected identifier checks. #3064

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions jerry-core/parser/js/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
*/
typedef enum
{
/* The LEXER_IS_IDENT_OR_STRING macro must be updated if the order is changed. */
LEXER_IDENT_LITERAL = 0, /**< identifier literal */
LEXER_STRING_LITERAL = 1, /**< string literal */
LEXER_NUMBER_LITERAL = 2, /**< number literal */
Expand All @@ -56,6 +57,11 @@ typedef enum
used by the byte code generator. */
} lexer_literal_type_t;

/**
* Checks whether the literal type is identifier or string.
*/
#define LEXER_IS_IDENT_OR_STRING(literal_type) ((literal_type) <= LEXER_STRING_LITERAL)

/**
* Flag bits for status_flags member of lexer_literal_t.
*/
Expand Down
61 changes: 39 additions & 22 deletions jerry-core/parser/js/js-lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2331,12 +2331,12 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
if (context_p->source_p < context_p->source_end_p
&& context_p->source_p[0] != LIT_CHAR_COLON)
{
if (lexer_compare_raw_identifier_to_current (context_p, "get", 3))
if (lexer_compare_literal_to_string (context_p, "get", 3))
{
context_p->token.type = LEXER_PROPERTY_GETTER;
return;
}
else if (lexer_compare_raw_identifier_to_current (context_p, "set", 3))
else if (lexer_compare_literal_to_string (context_p, "set", 3))
{
context_p->token.type = LEXER_PROPERTY_SETTER;
return;
Expand All @@ -2345,8 +2345,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
}

#if ENABLED (JERRY_ES2015_CLASS)
if (is_class_method
&& lexer_compare_raw_identifier_to_current (context_p, "static", 6))
if (is_class_method && lexer_compare_literal_to_string (context_p, "static", 6))
{
context_p->token.type = LEXER_KEYW_STATIC;
return;
Expand Down Expand Up @@ -2406,8 +2405,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
if (create_literal_object)
{
#if ENABLED (JERRY_ES2015_CLASS)
if (is_class_method
&& lexer_compare_raw_identifier_to_current (context_p, "constructor", 11))
if (is_class_method && lexer_compare_literal_to_string (context_p, "constructor", 11))
{
context_p->token.type = LEXER_CLASS_CONSTRUCTOR;
return;
Expand Down Expand Up @@ -2447,11 +2445,11 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */
if (context_p->source_p < context_p->source_end_p
&& context_p->source_p[0] != LIT_CHAR_COLON)
{
if (lexer_compare_raw_identifier_to_current (context_p, "get", 3))
if (lexer_compare_literal_to_string (context_p, "get", 3))
{
context_p->token.type = LEXER_PROPERTY_GETTER;
}
else if (lexer_compare_raw_identifier_to_current (context_p, "set", 3))
else if (lexer_compare_literal_to_string (context_p, "set", 3))
{
context_p->token.type = LEXER_PROPERTY_SETTER;
}
Expand Down Expand Up @@ -2573,27 +2571,46 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context *
} /* lexer_compare_identifier_to_current */

/**
* Compares the current identifier in the context to the parameter identifier
* Compares the current identifier to an expected identifier.
*
* Note:
* Escape sequences are not allowed.
*
* @return true if the input identifiers are the same
* @return true if they are the same, false otherwise
*/
bool
lexer_compare_raw_identifier_to_current (parser_context_t *context_p, /**< context */
const char *right_ident_p, /**< identifier */
size_t right_ident_length) /**< identifier length */
inline bool JERRY_ATTR_ALWAYS_INLINE
lexer_compare_literal_to_identifier (parser_context_t *context_p, /**< context */
const char *identifier_p, /**< identifier */
size_t identifier_length) /**< identifier length */
{
lexer_lit_location_t *left_ident_p = &context_p->token.lit_location;

if (left_ident_p->length != right_ident_length || left_ident_p->has_escape)
{
return 0;
}
/* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */
return (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL
&& context_p->token.lit_location.length == identifier_length
&& memcmp (context_p->token.lit_location.char_p, identifier_p, identifier_length) == 0);
} /* lexer_compare_literal_to_identifier */

return memcmp (left_ident_p->char_p, right_ident_p, right_ident_length) == 0;
} /* lexer_compare_raw_identifier_to_current */
/**
* Compares the current identifier or string to an expected string.
*
* Note:
* Escape sequences are not allowed.
*
* @return true if they are the same, false otherwise
*/
inline bool JERRY_ATTR_ALWAYS_INLINE
lexer_compare_literal_to_string (parser_context_t *context_p, /**< context */
const char *string_p, /**< string */
size_t string_length) /**< string length */
{
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL));

/* Checking has_escape is unnecessary because memcmp will fail if escape sequences are present. */
return (context_p->token.lit_location.length == string_length
&& memcmp (context_p->token.lit_location.char_p, string_p, string_length) == 0);
} /* lexer_compare_literal_to_string */

/**
* Convert binary lvalue token to binary token
Expand Down
6 changes: 4 additions & 2 deletions jerry-core/parser/js/js-parser-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,8 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */
is_computed = true;
}
else if (!(status_flags & PARSER_CLASS_STATIC_FUNCTION)
&& lexer_compare_raw_identifier_to_current (context_p, "constructor", 11))
&& LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make sense to have this LEXER_IS_IDENT_OR_STRING in the method? And not as an assert? The other variant of the method correctly checks the types without assert.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty low level function and in the other cases it knows that the type is limited to the allowed types.

&& lexer_compare_literal_to_string (context_p, "constructor", 11))
{
parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR);
}
Expand Down Expand Up @@ -531,7 +532,8 @@ parser_parse_class_literal (parser_context_t *context_p) /**< context */
is_computed = true;
}
else if ((status_flags & PARSER_CLASS_STATIC_FUNCTION)
&& lexer_compare_raw_identifier_to_current (context_p, "prototype", 9))
&& LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
&& lexer_compare_literal_to_string (context_p, "prototype", 9))
{
parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE);
}
Expand Down
5 changes: 3 additions & 2 deletions jerry-core/parser/js/js-parser-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,9 @@ 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);
void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only);
bool lexer_compare_identifier_to_current (parser_context_t *context_p, const lexer_lit_location_t *right_ident_p);
bool lexer_compare_raw_identifier_to_current (parser_context_t *context_p, const char *right_ident_p,
size_t right_ident_length);
bool lexer_compare_literal_to_identifier (parser_context_t *context_p, const char *identifier_p,
size_t identifier_length);
bool lexer_compare_literal_to_string (parser_context_t *context_p, const char *string_p, size_t string_length);
uint8_t lexer_convert_binary_lvalue_token_to_binary (uint8_t token);

/**
Expand Down
12 changes: 4 additions & 8 deletions jerry-core/parser/js/js-parser-module.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,7 @@ parser_module_parse_export_clause (parser_context_t *context_p) /**< parser cont
uint16_t export_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;

lexer_next_token (context_p);
if (context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
if (lexer_compare_literal_to_identifier (context_p, "as", 2))
{
lexer_next_token (context_p);

Expand Down Expand Up @@ -415,8 +414,7 @@ parser_module_parse_export_clause (parser_context_t *context_p) /**< parser cont
lexer_next_token (context_p);
}

if (context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
if (lexer_compare_literal_to_identifier (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
}
Expand Down Expand Up @@ -455,8 +453,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;

lexer_next_token (context_p);
if (context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
if (lexer_compare_literal_to_identifier (context_p, "as", 2))
{
lexer_next_token (context_p);

Expand Down Expand Up @@ -508,8 +505,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
lexer_next_token (context_p);
}

if (context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
if (lexer_compare_literal_to_identifier (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
}
Expand Down
8 changes: 4 additions & 4 deletions jerry-core/parser/js/js-parser-scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ parser_scan_until (parser_context_t *context_p, /**< context */
context_p->token.type = LEXER_KEYW_IN;
return;
}
else if (type == LEXER_LITERAL && lexer_compare_raw_identifier_to_current (context_p, "of", 2))
else if (lexer_compare_literal_to_identifier (context_p, "of", 2))
{
parser_stack_pop_uint8 (context_p);
context_p->token.type = LEXER_LITERAL_OF;
Expand Down Expand Up @@ -788,13 +788,13 @@ parser_scan_until (parser_context_t *context_p, /**< context */
break;
}

if (lexer_compare_raw_identifier_to_current (context_p, "static", 6))
if (lexer_compare_literal_to_identifier (context_p, "static", 6))
{
lexer_next_token (context_p);
}

if (lexer_compare_raw_identifier_to_current (context_p, "get", 3)
|| lexer_compare_raw_identifier_to_current (context_p, "set", 3))
if (lexer_compare_literal_to_identifier (context_p, "get", 3)
|| lexer_compare_literal_to_identifier (context_p, "set", 3))
{
lexer_next_token (context_p);
}
Expand Down
21 changes: 8 additions & 13 deletions jerry-core/parser/js/js-parser-statm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1884,12 +1884,6 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context

lexer_next_token (context_p);

if (context_p->token.type != LEXER_COMMA
&& !lexer_compare_raw_identifier_to_current (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED);
}

if (context_p->token.type == LEXER_COMMA)
{
lexer_next_token (context_p);
Expand All @@ -1899,14 +1893,17 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED);
}
}
else if (!lexer_compare_literal_to_identifier (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED);
}
}

if (context_p->token.type == LEXER_MULTIPLY)
{
/* NameSpaceImport*/
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL
|| !lexer_compare_raw_identifier_to_current (context_p, "as", 2))
if (!lexer_compare_literal_to_identifier (context_p, "as", 2))
{
parser_raise_error (context_p, PARSER_ERR_AS_EXPECTED);
}
Expand Down Expand Up @@ -1942,7 +1939,7 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context
parser_module_parse_import_clause (context_p);
}

if (context_p->token.type != LEXER_LITERAL || !lexer_compare_raw_identifier_to_current (context_p, "from", 4))
if (!lexer_compare_literal_to_identifier (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
}
Expand Down Expand Up @@ -2035,8 +2032,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
case LEXER_MULTIPLY:
{
lexer_next_token (context_p);
if (!(context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4)))
if (!lexer_compare_literal_to_identifier (context_p, "from", 4))
{
parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
}
Expand Down Expand Up @@ -2106,8 +2102,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
{
parser_module_parse_export_clause (context_p);

if (context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
if (lexer_compare_literal_to_identifier (context_p, "from", 4))
{
lexer_next_token (context_p);
parser_module_handle_module_specifier (context_p);
Expand Down
4 changes: 4 additions & 0 deletions tests/jerry/es2015/for-of.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ var forOf =
" obj[prop] += 4;"
parse (forOf)

var forOf =
"for (var a \"of\" []) {}"
parse (forOf)

checkError(5)

var obj = {}
Expand Down