summaryrefslogtreecommitdiff
path: root/Libraries/LibJS
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2020-09-12 10:22:36 +0100
committerAndreas Kling <kling@serenityos.org>2020-09-12 11:29:39 +0200
commit568d53c9b1eb81b38aaccd904cce682f8a7d0cf0 (patch)
tree3dfe0f0bbe95ae8a782636dd52dbfa27bfd568c0 /Libraries/LibJS
parent75dac35d0e66c173b3ceb5e8ecf44fe771b7cd87 (diff)
downloadserenity-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.cpp10
-rw-r--r--Libraries/LibJS/Tests/computed-property-throws.js8
-rw-r--r--Libraries/LibJS/Tests/exception-in-catch-block.js2
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;