1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:57:43 +00:00

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.
This commit is contained in:
Linus Groh 2020-09-12 10:22:36 +01:00 committed by Andreas Kling
parent 75dac35d0e
commit 568d53c9b1
3 changed files with 17 additions and 3 deletions

View file

@ -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); auto* this_value = is_super_property_lookup ? &interpreter.this_value(global_object).as_object() : lookup_target.to_object(interpreter, global_object);
if (interpreter.exception()) if (interpreter.exception())
return {}; 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 { this_value, callee };
} }
return { &global_object, m_callee->execute(interpreter, global_object) }; 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); auto* object_result = object_value.to_object(interpreter, global_object);
if (interpreter.exception()) if (interpreter.exception())
return {}; 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 Value StringLiteral::execute(Interpreter& interpreter, GlobalObject&) const

View file

@ -0,0 +1,8 @@
test("Issue #3459, exception in computed property expression", () => {
expect(() => {
"foo"[bar];
}).toThrow(ReferenceError);
expect(() => {
"foo"[bar]();
}).toThrow(ReferenceError);
});

View file

@ -1,4 +1,4 @@
test("Issue #1992, exception thrown in catch {} block", () => { test("Issue #3437, exception thrown in catch {} block", () => {
var tryHasBeenExecuted = false; var tryHasBeenExecuted = false;
var catchHasBeenExecuted = false; var catchHasBeenExecuted = false;
var finallyHasBeenExecuted = false; var finallyHasBeenExecuted = false;