diff options
author | Linus Groh <mail@linusgroh.de> | 2020-09-12 10:22:36 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-12 11:29:39 +0200 |
commit | 568d53c9b1eb81b38aaccd904cce682f8a7d0cf0 (patch) | |
tree | 3dfe0f0bbe95ae8a782636dd52dbfa27bfd568c0 /Libraries/LibJS | |
parent | 75dac35d0e66c173b3ceb5e8ecf44fe771b7cd87 (diff) | |
download | serenity-568d53c9b1eb81b38aaccd904cce682f8a7d0cf0.zip |
LibJS: Check validity of computed_property_name() result before using it
This fixes two cases obj[expr] and obj[expr]() (MemberExpression and
CallExpression respectively) when expr throws an exception and results
in an empty value, causing a crash by passing the invalid PropertyName
created by computed_property_name() to Object::get() without checking it
first.
Fixes #3459.
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r-- | Libraries/LibJS/AST.cpp | 10 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/computed-property-throws.js | 8 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/exception-in-catch-block.js | 2 |
3 files changed, 17 insertions, 3 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 19161b9749..3886950442 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -122,7 +122,10 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete auto* this_value = is_super_property_lookup ? &interpreter.this_value(global_object).as_object() : lookup_target.to_object(interpreter, global_object); if (interpreter.exception()) return {}; - auto callee = lookup_target.to_object(interpreter, global_object)->get(member_expression.computed_property_name(interpreter, global_object)).value_or(js_undefined()); + auto property_name = member_expression.computed_property_name(interpreter, global_object); + if (!property_name.is_valid()) + return {}; + auto callee = lookup_target.to_object(interpreter, global_object)->get(property_name).value_or(js_undefined()); return { this_value, callee }; } return { &global_object, m_callee->execute(interpreter, global_object) }; @@ -1589,7 +1592,10 @@ Value MemberExpression::execute(Interpreter& interpreter, GlobalObject& global_o auto* object_result = object_value.to_object(interpreter, global_object); if (interpreter.exception()) return {}; - return object_result->get(computed_property_name(interpreter, global_object)).value_or(js_undefined()); + auto property_name = computed_property_name(interpreter, global_object); + if (!property_name.is_valid()) + return {}; + return object_result->get(property_name).value_or(js_undefined()); } Value StringLiteral::execute(Interpreter& interpreter, GlobalObject&) const diff --git a/Libraries/LibJS/Tests/computed-property-throws.js b/Libraries/LibJS/Tests/computed-property-throws.js new file mode 100644 index 0000000000..9c999c50e7 --- /dev/null +++ b/Libraries/LibJS/Tests/computed-property-throws.js @@ -0,0 +1,8 @@ +test("Issue #3459, exception in computed property expression", () => { + expect(() => { + "foo"[bar]; + }).toThrow(ReferenceError); + expect(() => { + "foo"[bar](); + }).toThrow(ReferenceError); +}); diff --git a/Libraries/LibJS/Tests/exception-in-catch-block.js b/Libraries/LibJS/Tests/exception-in-catch-block.js index f84ad4cb41..2a0fa6e1fc 100644 --- a/Libraries/LibJS/Tests/exception-in-catch-block.js +++ b/Libraries/LibJS/Tests/exception-in-catch-block.js @@ -1,4 +1,4 @@ -test("Issue #1992, exception thrown in catch {} block", () => { +test("Issue #3437, exception thrown in catch {} block", () => { var tryHasBeenExecuted = false; var catchHasBeenExecuted = false; var finallyHasBeenExecuted = false; |