Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
b3d14c9d34 Fix Response constructor crash when passed a function as init
Fixes a stack overflow crash that occurred when passing a function as
the second argument (ResponseInit) to the Response constructor.

The issue was that the constructor checked `isObject()` which returns
true for functions, and then proceeded to call `Init.init()` which
would attempt to read properties from the function. This could cause
infinite recursion in certain edge cases.

The fix adds an explicit check to reject callable objects before
processing them as ResponseInit, throwing a proper TypeError instead
of causing a stack overflow.
2025-10-22 07:56:42 +00:00
2 changed files with 21 additions and 2 deletions

View File

@@ -715,11 +715,17 @@ pub fn constructor(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame, j
.headers = null,
};
}
if (arguments[1].isCallable()) {
if (!globalThis.hasException()) {
return globalThis.throwInvalidArguments("Failed to construct 'Response': The provided value is not of type 'ResponseInit'", .{});
}
return error.JSError;
}
if (arguments[1].isObject()) {
break :brk try Init.init(globalThis, arguments[1]) orelse unreachable;
}
if (!globalThis.hasException()) {
return globalThis.throwInvalidArguments("Failed to construct 'Response': The provided body value is not of type 'ResponseInit'", .{});
return globalThis.throwInvalidArguments("Failed to construct 'Response': The provided value is not of type 'ResponseInit'", .{});
}
return error.JSError;
});

View File

@@ -49,7 +49,7 @@ describe("2-arg form", () => {
test("print size", () => {
expect(normalizeBunSnapshot(Bun.inspect(new Response(Bun.file(import.meta.filename)))), import.meta.dir)
.toMatchInlineSnapshot(`
"Response (3.82 KB) {
"Response (4.28 KB) {
ok: true,
url: "",
status: 200,
@@ -109,3 +109,16 @@ test("new Response(123, { method: 456 }) does not throw", () => {
// @ts-expect-error
expect(() => new Response("123", { method: 456 })).not.toThrow();
});
test("Response constructor should reject function as init (regression test for stack overflow)", () => {
function f0() {
const v1 = [1046375616, -1024, -1024, -268435456, 536870887, -77930801, -53473, 24365];
// @ts-expect-error - Testing invalid usage
Response(v1, f0, f0).arrayBuffer(v1, Response);
v1.forEach(f0);
return Response;
}
// This should throw an error instead of causing a stack overflow
expect(() => f0()).toThrow();
});