Compare commits

...

2 Commits

Author SHA1 Message Date
autofix-ci[bot]
9ff046212f [autofix.ci] apply automated fixes 2026-02-21 04:26:35 +00:00
Claude
032b5e6428 fix: prevent assertion crash when SharedArrayBuffer-backed views reach unsharedBuffer() 2026-02-21 04:24:35 +00:00
3 changed files with 30 additions and 0 deletions

View File

@@ -189,9 +189,13 @@ template<> struct WebCore::Converter<Bun::IDLArrayBufferRef>
return jsBuffer;
}
if (auto* jsView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
if (jsView->isShared())
return std::nullopt;
return jsView->unsharedBuffer();
}
if (auto* jsDataView = JSC::jsDynamicCast<JSC::JSDataView*>(value)) {
if (jsDataView->isShared())
return std::nullopt;
return jsDataView->unsharedBuffer();
}
return std::nullopt;

View File

@@ -90,6 +90,11 @@ JSC_DEFINE_HOST_FUNCTION(structuredCloneForStream, (JSGlobalObject * globalObjec
auto* bufferView = jsCast<JSArrayBufferView*>(value);
ASSERT(bufferView);
if (bufferView->isShared()) {
throwDataCloneError(*globalObject, scope);
return {};
}
auto* buffer = bufferView->unsharedBuffer();
if (!buffer) {
throwDataCloneError(*globalObject, scope);

View File

@@ -0,0 +1,21 @@
import { expect, test } from "bun:test";
test("Response.clone() does not crash when body stream contains SharedArrayBuffer-backed typed array", async () => {
const sab = new SharedArrayBuffer(8);
const view = new Uint8Array(sab);
const stream = new ReadableStream({
start(controller) {
controller.enqueue(view);
controller.close();
},
});
const resp = new Response(stream);
const clone = resp.clone();
// Reading the cloned body triggers structuredCloneForStream on the chunk.
// Before the fix, this would crash with:
// ASSERTION FAILED: !result || !result->isShared()
// Now it should throw a DataCloneError instead of crashing.
expect(async () => await clone.arrayBuffer()).toThrow("cloned");
});