diff options
author | Stephan Unverwerth <s.unverwerth@gmx.de> | 2020-10-18 15:32:50 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-10-18 15:38:57 +0200 |
commit | 2c888b3c6e118fa4354aa21d5bed62e17bc045b4 (patch) | |
tree | fb0b0f5c381e3fd0360cbc56892a1d6f41806843 | |
parent | 3efd4c105fb3342a60e33ae2c1672f6a1542e021 (diff) | |
download | serenity-2c888b3c6e118fa4354aa21d5bed62e17bc045b4.zip |
LibJS: Fix parsing of invalid numeric literals
i.e. "1e" "0x" "0b" "0o" used to be parsed as valid literals.
They now produce invalid tokens. Fixes #3716
-rw-r--r-- | Libraries/LibJS/Lexer.cpp | 65 | ||||
-rw-r--r-- | Libraries/LibJS/Lexer.h | 5 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/numeric-literals-basic.js | 7 |
3 files changed, 63 insertions, 14 deletions
diff --git a/Libraries/LibJS/Lexer.cpp b/Libraries/LibJS/Lexer.cpp index 26a3a65a62..aa1bbbaf16 100644 --- a/Libraries/LibJS/Lexer.cpp +++ b/Libraries/LibJS/Lexer.cpp @@ -172,14 +172,56 @@ void Lexer::consume() m_current_char = m_source[m_position++]; } -void Lexer::consume_exponent() +bool Lexer::consume_exponent() { consume(); if (m_current_char == '-' || m_current_char == '+') consume(); + + if (!isdigit(m_current_char)) + return false; + while (isdigit(m_current_char)) { consume(); } + return true; +} + +bool Lexer::consume_octal_number() +{ + consume(); + if (!(m_current_char >= '0' && m_current_char <= '7')) + return false; + + while (m_current_char >= '0' && m_current_char <= '7') { + consume(); + } + + return true; +} + +bool Lexer::consume_hexadecimal_number() +{ + consume(); + if (!isxdigit(m_current_char)) + return false; + + while (isxdigit(m_current_char)) + consume(); + + return true; +} + +bool Lexer::consume_binary_number() +{ + consume(); + if (!(m_current_char == '0' || m_current_char == '1')) + return false; + + while (m_current_char == '0' || m_current_char == '1') + consume(); + + return true; } bool Lexer::match(char a, char b) const @@ -355,6 +397,7 @@ Token Lexer::next() } } else if (is_numeric_literal_start()) { token_type = TokenType::NumericLiteral; + bool is_invalid_numeric_literal = false; if (m_current_char == '0') { consume(); if (m_current_char == '.') { @@ -363,24 +406,18 @@ Token Lexer::next() while (isdigit(m_current_char)) consume(); if (m_current_char == 'e' || m_current_char == 'E') - consume_exponent(); + is_invalid_numeric_literal = !consume_exponent(); } else if (m_current_char == 'e' || m_current_char == 'E') { - consume_exponent(); + is_invalid_numeric_literal = !consume_exponent(); } else if (m_current_char == 'o' || m_current_char == 'O') { // octal - consume(); - while (m_current_char >= '0' && m_current_char <= '7') - consume(); + is_invalid_numeric_literal = !consume_octal_number(); } else if (m_current_char == 'b' || m_current_char == 'B') { // binary - consume(); - while (m_current_char == '0' || m_current_char == '1') - consume(); + is_invalid_numeric_literal = !consume_binary_number(); } else if (m_current_char == 'x' || m_current_char == 'X') { // hexadecimal - consume(); - while (isxdigit(m_current_char)) - consume(); + is_invalid_numeric_literal = !consume_hexadecimal_number(); } else if (m_current_char == 'n') { consume(); token_type = TokenType::BigIntLiteral; @@ -405,9 +442,11 @@ Token Lexer::next() consume(); } if (m_current_char == 'e' || m_current_char == 'E') - consume_exponent(); + is_invalid_numeric_literal = !consume_exponent(); } } + if (is_invalid_numeric_literal) + token_type = TokenType::Invalid; } else if (m_current_char == '"' || m_current_char == '\'') { char stop_char = m_current_char; consume(); diff --git a/Libraries/LibJS/Lexer.h b/Libraries/LibJS/Lexer.h index 18f9bfb2d3..95d514e25d 100644 --- a/Libraries/LibJS/Lexer.h +++ b/Libraries/LibJS/Lexer.h @@ -42,7 +42,10 @@ public: private: void consume(); - void consume_exponent(); + bool consume_exponent(); + bool consume_octal_number(); + bool consume_hexadecimal_number(); + bool consume_binary_number(); bool is_eof() const; bool is_identifier_start() const; bool is_identifier_middle() const; diff --git a/Libraries/LibJS/Tests/numeric-literals-basic.js b/Libraries/LibJS/Tests/numeric-literals-basic.js index 48d09a255c..652fa9d2c1 100644 --- a/Libraries/LibJS/Tests/numeric-literals-basic.js +++ b/Libraries/LibJS/Tests/numeric-literals-basic.js @@ -35,3 +35,10 @@ test("accessing properties of decimal numbers", () => { expect((1.1).foo).toBe("foo"); expect((0.1).foo).toBe("foo"); }); + +test("invalid numeric literals", () => { + expect("1e").not.toEval(); + expect("0x").not.toEval(); + expect("0b").not.toEval(); + expect("0o").not.toEval(); +}); |