From 697882a7ade03fb3ef483914ebfe513ef1d63cca Mon Sep 17 00:00:00 2001 From: davidot Date: Mon, 12 Jul 2021 01:32:01 +0200 Subject: [PATCH] LibJS: Disallow multiple __proto__ keys in object expression --- Userland/Libraries/LibJS/Parser.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index a36a41e649..3b312146dc 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -968,6 +968,11 @@ NonnullRefPtr Parser::parse_object_expression() consume(); }; + // It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate + // entries for "__proto__" and at least two of those entries were obtained from productions of + // the form PropertyDefinition : PropertyName : AssignmentExpression . + bool has_direct_proto_property = false; + while (!done() && !match(TokenType::CurlyClose)) { property_type = ObjectProperty::Type::KeyValue; RefPtr property_name; @@ -984,6 +989,8 @@ NonnullRefPtr Parser::parse_object_expression() continue; } + auto type = m_state.current_token.type(); + if (match(TokenType::Asterisk)) { consume(); property_type = ObjectProperty::Type::KeyValue; @@ -1005,6 +1012,8 @@ NonnullRefPtr Parser::parse_object_expression() property_name = parse_property_key(); } + bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is(*property_name) && static_cast(*property_name).value() == "__proto__"; + if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) { if (!match(TokenType::ParenOpen)) { expected("'(' for object getter or setter property"); @@ -1037,6 +1046,11 @@ NonnullRefPtr Parser::parse_object_expression() continue; } consume(); + if (is_proto) { + if (has_direct_proto_property) + syntax_error("Property name '__proto__' must not appear more than once in object literal"); + has_direct_proto_property = true; + } properties.append(create_ast_node({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, parse_expression(2), property_type, false)); } else if (property_name && property_value) { properties.append(create_ast_node({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, *property_value, property_type, false));