diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 1b28383086..48f090bb7a 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1212,11 +1212,19 @@ pub fn mmapFile(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun. } if (try opts.get(globalThis, "size")) |value| { - map_size = @as(usize, @intCast(value.toInt64())); + const size_value = try value.coerceToInt64(globalThis); + if (size_value < 0) { + return globalThis.throwInvalidArguments("size must be a non-negative integer", .{}); + } + map_size = @intCast(size_value); } if (try opts.get(globalThis, "offset")) |value| { - offset = @as(usize, @intCast(value.toInt64())); + const offset_value = try value.coerceToInt64(globalThis); + if (offset_value < 0) { + return globalThis.throwInvalidArguments("offset must be a non-negative integer", .{}); + } + offset = @intCast(offset_value); offset = std.mem.alignBackwardAnyAlign(usize, offset, std.heap.pageSize()); } } diff --git a/test/js/bun/util/mmap.test.js b/test/js/bun/util/mmap.test.js index 57a3f43e64..768550c855 100644 --- a/test/js/bun/util/mmap.test.js +++ b/test/js/bun/util/mmap.test.js @@ -68,4 +68,32 @@ describe.skipIf(isWindows)("Bun.mmap", async () => { expect(map[0]).toBe(old); await gcTick(); }); + + it("mmap rejects negative offset", () => { + expect(() => Bun.mmap(path, { offset: -1 })).toThrow("offset must be a non-negative integer"); + }); + + it("mmap rejects negative size", () => { + expect(() => Bun.mmap(path, { size: -1 })).toThrow("size must be a non-negative integer"); + }); + + it("mmap handles non-number offset/size without crashing", () => { + // These should not crash - non-number values coerce to 0 per JavaScript semantics + // Previously these caused assertion failures (issue ENG-22413) + + // null coerces to 0, which is valid for offset + expect(() => { + Bun.mmap(path, { offset: null }); + }).not.toThrow(); + + // size: null coerces to 0, which is invalid (EINVAL), but shouldn't crash + expect(() => { + Bun.mmap(path, { size: null }); + }).toThrow("EINVAL"); + + // undefined is ignored (property not set) + expect(() => { + Bun.mmap(path, { offset: undefined }); + }).not.toThrow(); + }); });