diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 7458131a86f..7e64c775255 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -4266,18 +4266,12 @@ bool Parser::match_declaration(AllowUsingDeclaration allow_using) const || type == TokenType::Let; } -Token Parser::next_token(size_t steps) const +Token Parser::next_token() const { - Lexer lookahead_lexer = m_state.lexer; - - Token lookahead_token; - - while (steps > 0) { - lookahead_token = lookahead_lexer.next(); - steps--; - } - - return lookahead_token; + // We need to keep the lookahead lexer alive to prevent UAF on the lookahead token, as the token may hold a view + // into a short string stored on the stack. + m_state.lookahead_lexer = m_state.lexer; + return m_state.lookahead_lexer->next(); } bool Parser::try_match_let_declaration() const diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h index c9d983ce939..edf4252d743 100644 --- a/Libraries/LibJS/Parser.h +++ b/Libraries/LibJS/Parser.h @@ -257,7 +257,7 @@ private: RefPtr synthesize_binding_pattern(Expression const& expression); - Token next_token(size_t steps = 1) const; + Token next_token() const; void check_identifier_name_for_assignment_validity(FlyString const&, bool force_strict = false); @@ -302,6 +302,7 @@ private: struct ParserState { Lexer lexer; + mutable Optional lookahead_lexer; Token current_token; bool previous_token_was_period { false }; Vector errors;