فهرست منبع

LibJS: Make sure private identifier is valid in optional chain

If we don't check that a private identifier is valid this can break the
assumption that we have a private environment when evaluation the
private identifier. Also an unknown private identifier this should
be a SyntaxError.
davidot 2 سال پیش
والد
کامیت
16ac43c9d4
2فایلهای تغییر یافته به همراه38 افزوده شده و 0 حذف شده
  1. 3 0
      Userland/Libraries/LibJS/Parser.cpp
  2. 35 0
      Userland/Libraries/LibJS/Tests/classes/class-private-fields.js

+ 3 - 0
Userland/Libraries/LibJS/Parser.cpp

@@ -3174,6 +3174,9 @@ NonnullRefPtr<OptionalChain> Parser::parse_optional_chain(NonnullRefPtr<Expressi
         } else if (match(TokenType::Period)) {
             consume();
             if (match(TokenType::PrivateIdentifier)) {
+                if (!is_private_identifier_valid())
+                    syntax_error(String::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
+
                 auto start = position();
                 auto private_identifier = consume();
                 chain.append(OptionalChain::PrivateMemberReference {

+ 35 - 0
Userland/Libraries/LibJS/Tests/classes/class-private-fields.js

@@ -148,3 +148,38 @@ test("using 'arguments' via indirect eval throws at runtime instead of parse tim
         }
     }).toThrowWithMessage(ReferenceError, "'arguments' is not defined");
 });
+
+test("unknown private name gives SyntaxError", () => {
+    expect(`#n`).not.toEval();
+    expect(`obj.#n`).not.toEval();
+    expect(`this.#n`).not.toEval();
+    expect(`if (#n) 1;`).not.toEval();
+    expect(`1?.#n`).not.toEval();
+    expect(`1?.n.#n`).not.toEval();
+});
+
+// OSS-FUZZ Issue 53363: top level unknown private names seg faults
+expect(() => eval(`#n`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);
+expect(() => eval(`obj.#n`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);
+expect(() => eval(`this.#n`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);
+expect(() => eval(`if (#n) 1;`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);
+expect(() => eval(`1?.#n`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);
+expect(() => eval(`1?.n.#n`)).toThrowWithMessage(
+    SyntaxError,
+    "Reference to undeclared private field or method '#n'"
+);