LibJS: Don't copy current program counter into new execution contexts

This didn't make any sense, and was already handled by pushing a new
execution context anyway.

By simply removing these bogus lines of code, we fix a bug where
throwing inside a function whose bytecode was shorter than the calling
function would crash trying to generate an Error stack trace (because
the bytecode offset we were trying to symbolicate was actually from
the longer caller function, and not valid in the callee function.)

This makes --log-all-js-exceptions less crash prone and more helpful.
This commit is contained in:
Andreas Kling 2024-09-08 11:12:15 +02:00 committed by Andreas Kling
parent 0c77b3bf59
commit b3f77e4769
Notes: github-actions[bot] 2024-09-08 09:34:39 +00:00
3 changed files with 20 additions and 4 deletions

View file

@ -387,7 +387,6 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
// Non-standard // Non-standard
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size())); callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size()));
callee_context->arguments.append(arguments_list.data(), arguments_list.size()); callee_context->arguments.append(arguments_list.data(), arguments_list.size());
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
callee_context->passed_argument_count = arguments_list.size(); callee_context->passed_argument_count = arguments_list.size();
if (arguments_list.size() < m_formal_parameters.size()) { if (arguments_list.size() < m_formal_parameters.size()) {
for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i) for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i)
@ -462,7 +461,6 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
// Non-standard // Non-standard
callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size())); callee_context->arguments.ensure_capacity(max(arguments_list.size(), m_formal_parameters.size()));
callee_context->arguments.append(arguments_list.data(), arguments_list.size()); callee_context->arguments.append(arguments_list.data(), arguments_list.size());
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
callee_context->passed_argument_count = arguments_list.size(); callee_context->passed_argument_count = arguments_list.size();
if (arguments_list.size() < m_formal_parameters.size()) { if (arguments_list.size() < m_formal_parameters.size()) {
for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i) for (size_t i = arguments_list.size(); i < m_formal_parameters.size(); ++i)

View file

@ -147,7 +147,6 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Read
// 8. Perform any necessary implementation-defined initialization of calleeContext. // 8. Perform any necessary implementation-defined initialization of calleeContext.
callee_context->this_value = this_argument; callee_context->this_value = this_argument;
callee_context->arguments.append(arguments_list.data(), arguments_list.size()); callee_context->arguments.append(arguments_list.data(), arguments_list.size());
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
callee_context->lexical_environment = caller_context.lexical_environment; callee_context->lexical_environment = caller_context.lexical_environment;
callee_context->variable_environment = caller_context.variable_environment; callee_context->variable_environment = caller_context.variable_environment;
@ -210,7 +209,6 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Reado
// 8. Perform any necessary implementation-defined initialization of calleeContext. // 8. Perform any necessary implementation-defined initialization of calleeContext.
callee_context->arguments.append(arguments_list.data(), arguments_list.size()); callee_context->arguments.append(arguments_list.data(), arguments_list.size());
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
callee_context->lexical_environment = caller_context.lexical_environment; callee_context->lexical_environment = caller_context.lexical_environment;
callee_context->variable_environment = caller_context.variable_environment; callee_context->variable_environment = caller_context.variable_environment;

View file

@ -0,0 +1,20 @@
test("Don't crash when throwing exception inside a callee smaller than the caller", () => {
function make() {
let o = {};
Object.defineProperty(o, "go", {
get: function () {
return doesNotExist;
},
});
return o;
}
// Some nonsense to make sure this function has a longer bytecode than the throwing getter.
function x() {
return 3;
}
function b() {}
b(x() + x() + x());
expect(() => make().go()).toThrowWithMessage(ReferenceError, "'doesNotExist' is not defined");
});