diff --git a/src/bun.js/webcore/blob/read_file.zig b/src/bun.js/webcore/blob/read_file.zig index 55ac7d5d40b..0da3918d8e3 100644 --- a/src/bun.js/webcore/blob/read_file.zig +++ b/src/bun.js/webcore/blob/read_file.zig @@ -347,10 +347,7 @@ pub const ReadFile = struct { // read up to 4k at a time if // they didn't explicitly set a size and we're reading from something that's not a regular file } else if (stat.size == 0 and this.could_block) { - this.size = if (this.max_length == Blob.max_size) - 4096 - else - this.max_length; + this.size = @min(this.max_length, 4096); } if (this.offset > 0) { @@ -384,7 +381,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; @@ -669,10 +666,7 @@ pub const ReadFileUV = struct { } else if (stat.size == 0 and !this.is_regular_file) { // read up to 4k at a time if they didn't explicitly set a size and // we're reading from something that's not a regular file. - this.size = if (this.max_length == Blob.max_size) - 4096 - else - this.max_length; + this.size = @min(this.max_length, 4096); } if (this.offset > 0) { diff --git a/test/js/bun/util/bun-file-read.test.ts b/test/js/bun/util/bun-file-read.test.ts index fd8bca82ac3..001b6d8f311 100644 --- a/test/js/bun/util/bun-file-read.test.ts +++ b/test/js/bun/util/bun-file-read.test.ts @@ -1,4 +1,5 @@ import { expect, it } from "bun:test"; +import { bunEnv, bunExe, isPosix } from "harness"; import { tmpdir } from "node:os"; it("offset should work in Bun.file() #4963", async () => { @@ -9,3 +10,29 @@ it("offset should work in Bun.file() #4963", async () => { const contents = await slice.text(); expect(contents).toBe("ntents"); }); + +it.skipIf(!isPosix)("reading a sliced non-regular file Blob does not overflow the initial buffer size", async () => { + // .slice(1) on a file Blob whose size is unknown (max_size) yields a Blob with + // size = max_size - 1. For a non-regular file (char device), this was used as + // the initial buffer capacity and `size + 16` overflowed u52. + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + const a = await Bun.file("/dev/null").slice(1).arrayBuffer(); + if (a.byteLength !== 0) throw new Error("expected 0, got " + a.byteLength); + const b = await Bun.file("/dev/zero").slice(0, 100).arrayBuffer(); + if (b.byteLength !== 100) throw new Error("expected 100, got " + b.byteLength); + console.log("ok"); + `, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, , exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect({ stdout: stdout.trim(), exitCode }).toEqual({ stdout: "ok", exitCode: 0 }); +});