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
Notes: sideshowbarker 2024-07-19 01:51:31 +09:00
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++];
}
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();

View file

@ -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;

View file

@ -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();
});