summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Unverwerth <s.unverwerth@gmx.de>2020-10-18 15:32:50 +0200
committerAndreas Kling <kling@serenityos.org>2020-10-18 15:38:57 +0200
commit2c888b3c6e118fa4354aa21d5bed62e17bc045b4 (patch)
treefb0b0f5c381e3fd0360cbc56892a1d6f41806843
parent3efd4c105fb3342a60e33ae2c1672f6a1542e021 (diff)
downloadserenity-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.cpp65
-rw-r--r--Libraries/LibJS/Lexer.h5
-rw-r--r--Libraries/LibJS/Tests/numeric-literals-basic.js7
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();
+});