Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions src/runtime/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1216,33 +1216,37 @@ pub fn mmapFile(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.
var map_size: ?usize = null;

if (args.nextEat()) |opts| {
flags.TYPE = if ((try opts.getBooleanLoose(globalThis, "shared")) orelse true)
.SHARED
else
.PRIVATE;

if (@hasField(std.c.MAP, "SYNC")) {
if ((try opts.getBooleanLoose(globalThis, "sync")) orelse false) {
flags.TYPE = .SHARED_VALIDATE;
flags.SYNC = true;
if (opts.isObject()) {
flags.TYPE = if ((try opts.getBooleanLoose(globalThis, "shared")) orelse true)
.SHARED
else
.PRIVATE;

if (@hasField(std.c.MAP, "SYNC")) {
if ((try opts.getBooleanLoose(globalThis, "sync")) orelse false) {
flags.TYPE = .SHARED_VALIDATE;
flags.SYNC = true;
}
}
}

if (try opts.get(globalThis, "size")) |value| {
const size_value = try value.coerceToInt64(globalThis);
if (size_value < 0) {
return globalThis.throwInvalidArguments("size must be a non-negative integer", .{});
if (try opts.get(globalThis, "size")) |value| {
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);
}
map_size = @intCast(size_value);
}

if (try opts.get(globalThis, "offset")) |value| {
const offset_value = try value.coerceToInt64(globalThis);
if (offset_value < 0) {
return globalThis.throwInvalidArguments("offset must be a non-negative integer", .{});
if (try opts.get(globalThis, "offset")) |value| {
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());
}
offset = @intCast(offset_value);
offset = std.mem.alignBackwardAnyAlign(usize, offset, std.heap.pageSize());
} else if (!opts.isUndefinedOrNull()) {
return globalThis.throwInvalidArguments("Expected options to be an object", .{});
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/js/bun/util/mmap.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ describe.skipIf(isWindows)("Bun.mmap", async () => {
expect(() => Bun.mmap(path, { size: -1 })).toThrow("size must be a non-negative integer");
});

it("mmap rejects non-object options", () => {
expect(() => Bun.mmap(path, 256)).toThrow("Expected options to be an object");
expect(() => Bun.mmap(path, "foo")).toThrow("Expected options to be an object");
expect(() => Bun.mmap(path, true)).toThrow("Expected options to be an object");
expect(() => Bun.mmap(path, undefined)).not.toThrow();
expect(() => Bun.mmap(path, null)).not.toThrow();
});

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)
Expand Down
Loading