Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
5d6223b6f4 Fix crash in Blob.stream() when passing undefined chunkSize
Fixed an assertion failure in JSC__JSValue__toInt64() that occurred when
Blob.stream() was called with an undefined argument.

The code checked if the argument was number/undefined/null, but then
unconditionally called toInt64() on it. This caused a crash when the
value was undefined because toInt64() asserts the value must be a
HeapBigInt or Number.

The fix adds an additional check to only call toInt64() when the argument
is actually a number, treating undefined/null as the default (0).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 03:42:13 +00:00
2 changed files with 64 additions and 1 deletions

View File

@@ -1987,7 +1987,9 @@ pub fn getStream(
return globalThis.throwInvalidArguments("chunkSize must be a number", .{});
}
recommended_chunk_size = @as(SizeType, @intCast(@max(0, @as(i52, @truncate(arguments[0].toInt64())))));
if (arguments[0].isNumber()) {
recommended_chunk_size = @as(SizeType, @intCast(@max(0, @as(i52, @truncate(arguments[0].toInt64())))));
}
}
const stream = try jsc.WebCore.ReadableStream.fromBlobCopyRef(
globalThis,

View File

@@ -0,0 +1,61 @@
import { expect, test } from "bun:test";
// Fuzzer found crash: Blob.stream() with undefined argument
// The issue was that toInt64() was called on undefined, causing an assertion failure
test("Blob.stream() should handle undefined chunkSize argument", async () => {
class C1 extends Array {}
const v2 = C1[9]; // undefined
const blob = new Blob();
// This should not crash
const stream = blob.stream(v2);
expect(stream).toBeDefined();
expect(stream).toBeInstanceOf(ReadableStream);
// Verify the stream works
const reader = stream.getReader();
const result = await reader.read();
expect(result.done).toBe(true);
});
test("Blob.stream() should handle null chunkSize argument", async () => {
const blob = new Blob();
// null should also work (treated as default)
const stream = blob.stream(null);
expect(stream).toBeDefined();
expect(stream).toBeInstanceOf(ReadableStream);
const reader = stream.getReader();
const result = await reader.read();
expect(result.done).toBe(true);
});
test("Blob.stream() should handle valid chunkSize argument", async () => {
const blob = new Blob(["hello world"]);
// Valid number should work
const stream = blob.stream(5);
expect(stream).toBeDefined();
expect(stream).toBeInstanceOf(ReadableStream);
const reader = stream.getReader();
const chunks: Uint8Array[] = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
expect(chunks.length).toBeGreaterThan(0);
});
test("Blob.stream() should reject non-number, non-null/undefined chunkSize", () => {
const blob = new Blob();
// Invalid types should throw
expect(() => blob.stream("invalid" as any)).toThrow();
expect(() => blob.stream({} as any)).toThrow();
expect(() => blob.stream([] as any)).toThrow();
});