From 5bd3812dd01252902babb573f27c6b331b16f52d Mon Sep 17 00:00:00 2001 From: robobun Date: Sun, 12 Apr 2026 04:27:16 +0000 Subject: [PATCH 1/2] Fix integer overflow in ReadFile buffer pre-allocation When a file Blob is sliced to a length near Blob.max_size (maxInt(u52)) and then read, computing the initial buffer capacity as size + 16 overflows u52 and panics in debug builds. Use saturating add so the allocation attempt proceeds (and fails with OOM, which is already handled) instead of crashing. --- src/bun.js/webcore/blob/read_file.zig | 4 ++-- test/js/bun/util/bun-file-read.test.ts | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/bun.js/webcore/blob/read_file.zig b/src/bun.js/webcore/blob/read_file.zig index 55ac7d5d40b..017e86c741b 100644 --- a/src/bun.js/webcore/blob/read_file.zig +++ b/src/bun.js/webcore/blob/read_file.zig @@ -384,7 +384,7 @@ pub const ReadFile = struct { // add an extra 16 bytes to the buffer to avoid having to resize it for trailing extra data if (!this.could_block or (this.size > 0 and this.size != Blob.max_size)) - this.buffer = std.ArrayListUnmanaged(u8).initCapacity(bun.default_allocator, this.size + 16) catch |err| { + this.buffer = std.ArrayListUnmanaged(u8).initCapacity(bun.default_allocator, this.size +| 16) catch |err| { this.errno = err; this.onFinish(); return; @@ -698,7 +698,7 @@ pub const ReadFileUV = struct { return; } // add an extra 16 bytes to the buffer to avoid having to resize it for trailing extra data - this.buffer.ensureTotalCapacityPrecise(this.byte_store.allocator, @min(this.size + 16, @as(usize, std.math.maxInt(bun.windows.ULONG)))) catch { + this.buffer.ensureTotalCapacityPrecise(this.byte_store.allocator, @min(this.size +| 16, @as(usize, std.math.maxInt(bun.windows.ULONG)))) catch { this.errno = error.OutOfMemory; this.system_error = bun.sys.Error.fromCode(bun.sys.E.NOMEM, .read).toSystemError(); this.onFinish(); diff --git a/test/js/bun/util/bun-file-read.test.ts b/test/js/bun/util/bun-file-read.test.ts index fd8bca82ac3..84731ae342c 100644 --- a/test/js/bun/util/bun-file-read.test.ts +++ b/test/js/bun/util/bun-file-read.test.ts @@ -1,5 +1,6 @@ import { expect, it } from "bun:test"; import { tmpdir } from "node:os"; +import { bunEnv, bunExe, isPosix } from "harness"; it("offset should work in Bun.file() #4963", async () => { const filename = tmpdir() + "/bun.test.offset.txt"; @@ -9,3 +10,19 @@ it("offset should work in Bun.file() #4963", async () => { const contents = await slice.text(); expect(contents).toBe("ntents"); }); + +it.skipIf(!isPosix)("reading a file blob sliced to near Blob.max_size should not crash", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + `await Bun.file("/dev/zero").slice(0, 4503599627370490).text().then(() => {}, () => {});`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + const exitCode = await proc.exited; + expect(proc.signalCode).toBeNull(); + expect(exitCode).toBe(0); +}); From d08e2ff4495bba439055010a7500c5a66296ad53 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 04:29:30 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- test/js/bun/util/bun-file-read.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/js/bun/util/bun-file-read.test.ts b/test/js/bun/util/bun-file-read.test.ts index 84731ae342c..760690fcce2 100644 --- a/test/js/bun/util/bun-file-read.test.ts +++ b/test/js/bun/util/bun-file-read.test.ts @@ -1,6 +1,6 @@ import { expect, it } from "bun:test"; -import { tmpdir } from "node:os"; import { bunEnv, bunExe, isPosix } from "harness"; +import { tmpdir } from "node:os"; it("offset should work in Bun.file() #4963", async () => { const filename = tmpdir() + "/bun.test.offset.txt"; @@ -13,11 +13,7 @@ it("offset should work in Bun.file() #4963", async () => { it.skipIf(!isPosix)("reading a file blob sliced to near Blob.max_size should not crash", async () => { await using proc = Bun.spawn({ - cmd: [ - bunExe(), - "-e", - `await Bun.file("/dev/zero").slice(0, 4503599627370490).text().then(() => {}, () => {});`, - ], + cmd: [bunExe(), "-e", `await Bun.file("/dev/zero").slice(0, 4503599627370490).text().then(() => {}, () => {});`], env: bunEnv, stdout: "pipe", stderr: "pipe",