1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:17:44 +00:00

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
This commit is contained in:
Stephan Unverwerth 2020-10-18 15:32:50 +02:00 committed by Andreas Kling
parent 3efd4c105f
commit 2c888b3c6e
3 changed files with 63 additions and 14 deletions

View file

@ -172,14 +172,56 @@ void Lexer::consume()
m_current_char = m_source[m_position++]; m_current_char = m_source[m_position++];
} }
void Lexer::consume_exponent() bool Lexer::consume_exponent()
{ {
consume(); consume();
if (m_current_char == '-' || m_current_char == '+') if (m_current_char == '-' || m_current_char == '+')
consume(); consume();
if (!isdigit(m_current_char))
return false;
while (isdigit(m_current_char)) { while (isdigit(m_current_char)) {
consume(); 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 bool Lexer::match(char a, char b) const
@ -355,6 +397,7 @@ Token Lexer::next()
} }
} else if (is_numeric_literal_start()) { } else if (is_numeric_literal_start()) {
token_type = TokenType::NumericLiteral; token_type = TokenType::NumericLiteral;
bool is_invalid_numeric_literal = false;
if (m_current_char == '0') { if (m_current_char == '0') {
consume(); consume();
if (m_current_char == '.') { if (m_current_char == '.') {
@ -363,24 +406,18 @@ Token Lexer::next()
while (isdigit(m_current_char)) while (isdigit(m_current_char))
consume(); consume();
if (m_current_char == 'e' || m_current_char == 'E') 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') { } 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') { } else if (m_current_char == 'o' || m_current_char == 'O') {
// octal // octal
consume(); is_invalid_numeric_literal = !consume_octal_number();
while (m_current_char >= '0' && m_current_char <= '7')
consume();
} else if (m_current_char == 'b' || m_current_char == 'B') { } else if (m_current_char == 'b' || m_current_char == 'B') {
// binary // binary
consume(); is_invalid_numeric_literal = !consume_binary_number();
while (m_current_char == '0' || m_current_char == '1')
consume();
} else if (m_current_char == 'x' || m_current_char == 'X') { } else if (m_current_char == 'x' || m_current_char == 'X') {
// hexadecimal // hexadecimal
consume(); is_invalid_numeric_literal = !consume_hexadecimal_number();
while (isxdigit(m_current_char))
consume();
} else if (m_current_char == 'n') { } else if (m_current_char == 'n') {
consume(); consume();
token_type = TokenType::BigIntLiteral; token_type = TokenType::BigIntLiteral;
@ -405,9 +442,11 @@ Token Lexer::next()
consume(); consume();
} }
if (m_current_char == 'e' || m_current_char == 'E') 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 == '\'') { } else if (m_current_char == '"' || m_current_char == '\'') {
char stop_char = m_current_char; char stop_char = m_current_char;
consume(); consume();

View file

@ -42,7 +42,10 @@ public:
private: private:
void consume(); 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_eof() const;
bool is_identifier_start() const; bool is_identifier_start() const;
bool is_identifier_middle() const; bool is_identifier_middle() const;

View file

@ -35,3 +35,10 @@ test("accessing properties of decimal numbers", () => {
expect((1.1).foo).toBe("foo"); expect((1.1).foo).toBe("foo");
expect((0.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();
});