Skip to content

Bun.mmap: return view at requested offset, not page-aligned offset - #34120

Merged
Jarred-Sumner merged 5 commits into
mainfrom
farm/de2993fd/fix-mmap-offset
Jul 19, 2026
Merged

Jarred-Sumner merged 5 commits into
mainfrom
farm/de2993fd/fix-mmap-offset

Conversation

@robobun

@robobun robobun commented Jul 14, 2026 •

Copy link
Copy Markdown
Collaborator

Reproduction

import * as fs from "node:fs";
const f = "/tmp/mmap-offset.bin";
const buf = Buffer.alloc(8192);
for (let i = 0; i < buf.length; i++) buf[i] = i & 0xff;
fs.writeFileSync(f, buf);

for (const off of [100, 1, 4095, 4097]) {
  const m = Bun.mmap(f, { offset: off });
  console.log(`offset=${off}: len=${m.length} [0]=${m[0]} want=${buf[off]}`);
}

Before:

offset=100:  len=8192 [0]=0 want=100
offset=1:    len=8192 [0]=0 want=1
offset=4095: len=8192 [0]=0 want=255
offset=4097: len=4096 [0]=0 want=1

After:

offset=100:  len=8092 [0]=100 want=100
offset=1:    len=8191 [0]=1   want=1
offset=4095: len=4097 [0]=255 want=255
offset=4097: len=4095 [0]=1   want=1

Cause

mmap(2) requires the file offset to be a multiple of the page size. mmap_file in src/runtime/api/BunObject.rs handled this by rounding the requested offset down to a page boundary (offset -= offset % page) and passing that to bun_sys::mmap_file, but then returned the raw mapping base as the Uint8Array data pointer. The view was never adjusted for the rounding delta, so index 0 pointed at the page boundary instead of the requested byte. Through a shared writable mapping, writes landed at the wrong file position too.

Fix

bun_sys::mmap_file now accepts the requested (unaligned) offset, computes delta = offset % page_size, maps view_size + delta bytes from the aligned offset, and returns (full_map, delta). The Bun.mmap wrapper hands JSC a Uint8Array over map_base + delta .. map_base + map_len. The deallocator recovers the mmap base by rounding the view pointer down to a page boundary (the kernel guarantees map_base is page-aligned and delta < page_size) and munmaps the full mapping length carried in the context pointer.

A non-aligned offset at or past EOF now yields a zero-length mapping request and throws EINVAL, matching the existing behavior for page-aligned offsets past EOF. Previously it returned the bytes between the page boundary and EOF.

Verification

test/js/bun/util/mmap.test.js gains three tests covering read position, shared-write position, and offset past EOF across aligned and unaligned offsets with and without size. All three fail on main and pass with this change; the existing eight mmap tests continue to pass.


no test proof · iteration 3 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/bun/util/mmap.test.js

@robobun

robobun commented Jul 14, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 8:05 PM PT - Jul 18th, 2026

❌ @robobun, your commit 6d6510e has 5 failures in Build #75570 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 34120

That installs a local version of the PR into your bun-34120 executable, so you can run:

bun-34120 --bun

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Changes

Bun’s mmap implementation now page-aligns file offsets, returns a mapping delta, exposes the requested Uint8Array region, and unmaps the full underlying mapping. Tests cover offset reads, shared writes, lengths, and invalid offsets.

mmap offset and cleanup

Layer / File(s) Summary
Page-aligned mapping contract
src/sys/lib.rs
mmap_file maps from a page-aligned offset, returns the full mapping with its offset delta, and handles zero-length mappings.
JavaScript view and cleanup
src/runtime/api/BunObject.rs
Bun.mmap creates a view from the mapping delta, while finalization rounds the pointer to the page boundary and unmaps the full mapping length.
Offset behavior validation
test/js/bun/util/mmap.test.js
Tests cover offset-based contents and lengths, shared writes, and EINVAL for offsets at or beyond EOF.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: Bun.mmap now returns a view at the requested offset.
Description check ✅ Passed The description includes the purpose and verification details, but it does not follow the template headings exactly.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/js/bun/util/mmap.test.js`:
- Around line 73-105: Refactor the parameterized mmap test around the cases
array to use it.each(cases), passing each offset/size case into its own test
invocation. Preserve the existing assertions and gcTick cleanup while removing
the manual for loop so each case is reported and isolated independently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 354da5a9-d799-4d84-aaac-2d34b7ec2571

📥 Commits

Reviewing files that changed from the base of the PR and between 16c5576 and e50bcc1.

📒 Files selected for processing (3)
  • src/runtime/api/BunObject.rs
  • src/sys/lib.rs
  • test/js/bun/util/mmap.test.js

Comment thread test/js/bun/util/mmap.test.js Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find any bugs, but this changes unsafe mmap/munmap pointer handling (the deallocator now recovers the mapping base via page-rounding), so it's worth a human look.

What was reviewed:

  • Verified bun_sys::mmap_file has no other callers, so the signature change is safe.
  • Checked delta < map_len holds on the success path (size==0 → EINVAL, else map_len = size + delta), so view_ptr/view_len stay in-bounds.
  • Confirmed bun_sys::page_size() and bun_alloc::page_size() are the same function, so map-time and dealloc-time deltas agree.
  • make_typed_array_with_bytes_no_copy docs confirm the deallocator receives the original ptr, so page-rounding recovers map_base exactly.
Extended reasoning...

Overview

This PR fixes Bun.mmap({offset}) to return a view starting at the requested byte instead of the page-aligned boundary. It touches three files: src/sys/lib.rs changes mmap_file to compute delta = offset % page_size, map size + delta bytes from the aligned offset, and return (map, delta); src/runtime/api/BunObject.rs slices the returned mapping by delta before handing it to JSC and updates the deallocator to round the view pointer down to a page boundary to recover the munmap base; test/js/bun/util/mmap.test.js adds three test blocks (9 offset/size combinations, shared-write positioning, offset-past-EOF).

Security risks

None identified. The mmap path is only reachable via the explicit Bun.mmap() API on files the process can already open RDWR. Size arithmetic (size + delta) is bounded by stat_size - offset + page_size, which cannot realistically overflow on 64-bit. The requested-size clamp (size.min(wanted_size)) is unchanged.

Level of scrutiny

This is memory-safety-sensitive native code: unsafe pointer arithmetic, a changed syscall-wrapper signature, and a custom JSC deallocator that now relies on a non-local invariant (mmap returns a page-aligned base and delta < page_size) to recover the munmap address. The reasoning is sound and well-commented, and the tests exercise the finalizer via gcTick(), but per this repo's review norms memory-management changes are the most-blocked category and warrant a maintainer sign-off rather than bot approval.

Other factors

There is a minor intentional behavior change: an unaligned offset at/past EOF now throws EINVAL instead of returning the bytes between the page boundary and EOF. This is documented in the PR description and tested, and it makes the aligned/unaligned cases consistent, but it is user-visible. CodeRabbit's only feedback (use it.each) was addressed in f22e3a6. No prior claude[bot] review on this PR.

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

@robobun fix clippy

@robobun

robobun commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Merged main in b1f38e2 to pick up the // SAFETY: comment in napi_body.rs::free_orphaned that clippy was flagging; that line isn't touched by this diff. cargo clippy --workspace is clean locally and all 19 mmap tests pass.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the inline nit, I checked a few memory-safety concerns and ruled them out: bun_sys::page_size is a re-export of bun_alloc::page_size (src/sys/lib.rs:3554), so the delta computed at map time and the round-down in munmap_dealloc agree; view_ptr = map_base + delta with map_base page-aligned and delta < page means addr - addr % page recovers exactly map_base; and bun_sys::mmap_file has no other callers, so the signature change is contained. Leaving native mmap/munmap pointer arithmetic for a human to sign off on.

Extended reasoning...

This PR changes the deallocator contract for Bun.mmap's backing ArrayBuffer and adds pointer arithmetic on both the map and unmap sides. I traced the invariants and they hold, but per repo guidance native memory-safety changes get a human look. The one finding (tempDir leak) is cosmetic and doesn't affect the fix.

Comment thread test/js/bun/util/mmap.test.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/js/bun/util/mmap.test.js (1)

123-130: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add an explicit numeric size: 0 regression case.

The EOF tests cover implicit zero-length mappings, but not { offset: 0, size: 0 }. The mmap contract maps any resulting zero length to EINVAL; lock this behavior with an explicit assertion.

Proposed test
     expect(() => Bun.mmap(file, { offset: 100 })).toThrow("EINVAL");
     expect(() => Bun.mmap(file, { offset: 50 })).toThrow("EINVAL");
+    expect(() => Bun.mmap(file, { offset: 0, size: 0 })).toThrow("EINVAL");

As per coding guidelines, every behavioral change must include an automated test in the same PR.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/js/bun/util/mmap.test.js` around lines 123 - 130, Add an explicit
assertion in the “mmap offset past EOF throws EINVAL” test for Bun.mmap with
offset 0 and numeric size 0, verifying it throws EINVAL while preserving the
existing implicit zero-length offset cases.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@test/js/bun/util/mmap.test.js`:
- Around line 123-130: Add an explicit assertion in the “mmap offset past EOF
throws EINVAL” test for Bun.mmap with offset 0 and numeric size 0, verifying it
throws EINVAL while preserving the existing implicit zero-length offset cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a99f3e6c-ce6e-4dad-92cd-2606d4c94297

📥 Commits

Reviewing files that changed from the base of the PR and between b1f38e2 and 25a3d9c.

📒 Files selected for processing (1)
  • test/js/bun/util/mmap.test.js

@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Skipping the { offset: 0, size: 0 } suggestion: the existing "mmap handles non-number offset/size without crashing" test already asserts Bun.mmap(path, { size: null }) throws EINVAL (null coerces to 0), which exercises the same map_len == 0 path. That behavior is also unchanged by this PR since delta == 0 at offset: 0.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new issues found — the earlier tempDir-leak nit is now addressed with afterAll(() => dir[Symbol.dispose]()). I'm deferring rather than approving because munmap_dealloc now recovers the mmap base by page-rounding the view pointer JSC hands back; that's unsafe pointer arithmetic in a GC finalizer and worth a human glance even though the invariant (mmap returns page-aligned, delta < page_size, JSC passes back the exact bytes pointer) checks out.

Checked: bun_sys::page_size is a re-export of bun_alloc::page_size (src/sys/lib.rs:3554), so the delta computation and the dealloc round-down use the same value. mmap_file has no other callers, so the signature change is contained. The offset=0 path is byte-identical to the old behavior (delta=0, view_ptr=map_base, map_len=view_len).

Extended reasoning...

Overview

Fixes Bun.mmap returning data at the page-aligned floor of offset instead of the requested byte. Three files: src/sys/lib.rs changes mmap_file to compute the page-alignment delta internally and return (full_map, delta); src/runtime/api/BunObject.rs slices the JSC Uint8Array to [map_base+delta, map_base+map_len) and updates munmap_dealloc to round the view pointer down to a page boundary before munmaping the full map_len carried in the ctx pointer; test/js/bun/util/mmap.test.js adds an it.each over 9 offset/size cases plus a shared-write test and an offset-past-EOF test.

Security risks

None identified. Bun.mmap is already a raw-memory API gated on a real path the caller controls; this change narrows the returned view rather than widening it. size + delta cannot overflow: size ≤ stat_size - offset and delta ≤ offset, so size + delta ≤ stat_size which already fit in usize.

Level of scrutiny

High. This is unsafe native code (raw mmap/munmap, from_raw_parts_mut, pointer .add()) with a JSC finalizer that now does arithmetic to recover a base pointer it wasn't directly given. REVIEW.md flags memory safety as the most-blocked category; a wrong munmap address is UB. The invariants relied on are solid — POSIX guarantees mmap returns a page-aligned address, delta < page_size by construction, and JSC's JSTypedArrayBytesDeallocator contract passes back the exact bytes pointer — but this is the kind of clever-but-load-bearing trick a maintainer should sign off on rather than a bot.

Other factors

  • Only caller of bun_sys::mmap_file is Bun.mmap, so the return-type change is fully contained.
  • bun_sys::page_size re-exports bun_alloc::page_size, so map-time and dealloc-time agree.
  • offset=0 path (delta=0) reduces exactly to the pre-PR behavior.
  • The map_len = if size == 0 { 0 } else { size + delta } branch preserves the existing EINVAL for offset ≥ EOF instead of silently returning the leading page-boundary bytes.
  • My prior inline nit (describe-scoped tempDir never disposed) was fixed in 25a3d9c with afterAll; all review threads are resolved.
  • Test coverage is thorough (aligned/unaligned offsets, boundary at 4095/4096/4097, explicit size clamping, oversize size, shared-write position, past-EOF), and tests hardcode 4096 which is fine since Linux/macOS CI runners use 4K or 16K pages and the delta logic is page-size-agnostic — the assertions compare against file contents, not page math.
  • Jarred has engaged on the PR (clippy fix request, now resolved) but hasn't reviewed the substance yet.

@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Build #75548 is failing across ~20 test files (bake, install, http, etc.) on all platforms with ReferenceError: listenerCountSlow is not defined at node:events:355. That came in via the main merge: efab3b2 (#34605) removed listenerCountSlow from src/js/node/events.ts but left a call to it in EventEmitterPrototype.listenerCount (line 525). Still present on current main.

None of it touches this diff. The mmap changes passed every buildkite lane in #72723 and test/js/bun/util/mmap.test.js is not in the #75548 failure set; clippy/Format/Lint are green. Ready to merge once main is fixed, or I can drop the main merge and carry just the one-line napi_body.rs clippy fix if preferred.

@robobun
robobun force-pushed the farm/de2993fd/fix-mmap-offset branch from 25a3d9c to f86852c Compare July 19, 2026 00:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/js/bun/util/mmap.test.js`:
- Around line 123-130: Extend the “mmap offset past EOF throws EINVAL” test to
call Bun.mmap with { offset: 1, size: 0 } and assert it throws EINVAL, covering
zero-size mappings at a non-page-aligned offset while preserving the existing
assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: aaebeb38-7086-4874-bb73-bfde73c5e3fb

📥 Commits

Reviewing files that changed from the base of the PR and between 25a3d9c and f86852c.

📒 Files selected for processing (3)
  • src/runtime/api/BunObject.rs
  • src/sys/lib.rs
  • test/js/bun/util/mmap.test.js

Comment thread test/js/bun/util/mmap.test.js

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix looks correct and my earlier tempDir note is resolved, but this reworks the munmap deallocator to recover the mapping base via page-rounding of the JSC-held view pointer — memory-safety-sensitive enough that a maintainer should sign off.

What was reviewed:

  • Verified bun_sys::mmap_file has no other callers, so the signature change to (map, delta) is contained.
  • Checked the deallocator invariant: bun_sys::page_size re-exports bun_alloc::page_size (same cached value at map and unmap time), mmap(NULL, …) returns a page-aligned base, and delta < page, so addr - addr % page recovers map_base exactly.
  • Checked size + delta cannot overflow (size ≤ stat_size - offset and delta ≤ offset), and delta < map_len holds whenever mmap succeeds, so .add(delta) stays in-bounds.
Extended reasoning...

Overview

The PR fixes Bun.mmap's offset option, which previously rounded down to a page boundary and returned the view at that boundary rather than at the requested byte. The fix moves page-alignment into bun_sys::mmap_file (src/sys/lib.rs), which now returns (full_map, delta); BunObject.rs builds the Uint8Array over map_base + delta .. map_base + map_len and passes map_len as the deallocator context. The deallocator rounds the view pointer down to a page boundary to recover map_base and munmaps the full length. Three new test blocks cover read position, shared-write position, and offset-past-EOF across aligned and unaligned offsets.

Security risks

None in the auth/crypto/injection sense. The relevant risk is memory safety: the munmap deallocator now derives the mapping base by page-rounding a pointer JSC hands back, rather than receiving the base directly. The reasoning is sound (mmap with addr=NULL guarantees page-aligned base; delta < page_size; page_size() is a process-wide OnceLock), but a wrong assumption here would be a UAF or a leaked mapping.

Level of scrutiny

Higher than a mechanical fix. This is native code doing raw pointer arithmetic inside a GC-driven deallocator callback, changes a bun_sys function's return type, and is a user-visible behavioral change (returned length shrinks by delta and index 0 moves). REVIEW.md flags native memory safety as the most-blocked category; this isn't the place for bot-only approval.

Other factors

All prior review threads (CodeRabbit's it.each refactor, my tempDir cleanup note, the {offset:1, size:0} coverage ask) are resolved in the current diff. Jarred engaged on the PR (clippy) but hasn't approved. The mmap tests passed on all lanes in build #72723; #75548's failures were an unrelated main-merge regression in node:events; #75561 on the latest commit was still building when I looked. Given the maintainer is already in the loop and the change sits squarely in memory-safety territory, deferring is the right call.

robobun and others added 5 commits July 19, 2026 01:20
Bun.mmap(path, { offset: N }) with a non-page-aligned N silently rounded
N down to the nearest page boundary and returned the mapping base. A
request for { offset: 100 } returned the file from byte 0 with length
st_size, so reads and shared-mapping writes both landed at the wrong
file position.

mmap(2) requires a page-aligned file offset, so bun_sys::mmap_file now
computes delta = offset % page_size, maps from the aligned offset with
delta extra bytes, and reports delta alongside the full mapping. The
Bun.mmap wrapper hands JSC a Uint8Array view at map_base + delta with
the requested length; the deallocator rounds the view pointer back down
to the page boundary (map_base is always page-aligned, delta < page) and
munmaps the full mapping length carried in the context pointer.

An offset at or past EOF now yields a zero-length mapping request and
throws EINVAL, matching the existing behavior for page-aligned offsets
past EOF.
@robobun
robobun force-pushed the farm/de2993fd/fix-mmap-offset branch from dc2d9ec to 6d6510e Compare July 19, 2026 01:22

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the offset-delta bookkeeping and the page-round-down recovery in munmap_dealloc check out.

Reviewed:

  • munmap_dealloc recovers map_base correctly: kernel returns a page-aligned base for addr=NULL, delta < page_size, and bun_sys::page_size is the same cached bun_alloc::page_size used at map time.
  • size + delta cannot overflow: after min(wanted_size), size ≤ stat_size - offset and delta ≤ offset, so map_len ≤ stat_size.
  • bun_sys::mmap_file's only caller is Bun.mmap; no other sites need the tuple return.
  • Tests don't assume a 4K page size — assertions key off buf[offset], so macOS arm64 (16K pages) is covered.
Extended reasoning...

Overview

Fixes Bun.mmap returning a view at the page-aligned offset instead of the requested offset. bun_sys::mmap_file (src/sys/lib.rs) now computes delta = offset % page_size, maps size + delta bytes from the aligned offset, and returns (map, delta). The Bun.mmap wrapper (src/runtime/api/BunObject.rs) hands JSC a Uint8Array over map_base + delta .. map_base + map_len and the deallocator recovers the mmap base by rounding the view pointer down to a page boundary before calling munmap with the full mapping length carried in the ctx pointer. Three new test blocks in test/js/bun/util/mmap.test.js cover read position, shared-write position, and past-EOF/zero-size across aligned and unaligned offsets.

Security risks

None. Input is a local file path already accepted by the existing Bun.mmap surface; no new untrusted-length arithmetic reaches an allocation without being clamped by stat_size. The unsafe pointer arithmetic is bounded: view_ptr = base.add(delta) with delta < map_len (guaranteed since the Ok arm is only reached when map_len = size + delta > 0, i.e. size > 0), and the deallocator's addr - addr % page is exact because the kernel returns page-aligned addresses and delta < page.

Level of scrutiny

Medium-high — this is native code with unsafe pointer arithmetic in a GC-time finalizer, where an off-by-one becomes a UAF or a mapping leak. I traced each invariant: (1) bun_sys::page_size() in the deallocator is a re-export of bun_alloc::page_size() used at map time (same cached OnceLock), so no divergence; (2) make_typed_array_with_bytes_no_copy's contract passes the exact ptr to the deallocator, so view_ptr is what munmap_dealloc receives; (3) size + delta is bounded by stat_size (since size ≤ stat_size - offset after the min, and delta = offset % page ≤ offset), so no overflow; (4) mmap_file has exactly one caller, so the signature change is self-contained.

Other factors

All prior review feedback has been addressed and the threads are resolved: the it.each refactor, the afterAll cleanup for the shared tempDir, and the {offset: 1, size: 0} EINVAL case. Jarred engaged on the PR and asked only for a clippy fix (unrelated to this diff, picked up via main merge). The reported CI failures on build #75548 are an unrelated node:events regression from main. Test coverage is thorough — 9 offset/size combinations plus write-through and error-path assertions, all with gcTick() to exercise the finalizer — and the tests are page-size-agnostic (assertions key off buf[offset], not a hardcoded boundary), so they hold on 16K-page platforms too.

@robobun

robobun commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto 20b4a0b (past the node:events fix in #34667). Build #75570: 278/286 jobs pass, clippy/Format/Lint green, test/js/bun/util/mmap.test.js passes on every lane.

Remaining red is unrelated to this diff:

  • test-worker-message-port-transfer-terminate.js (SIGABRT, ASAN) and test-net-connect-memleak.js (Alpine x64) are pre-existing on main
  • node-net.test.ts, no-orphans.test.ts, node-http-server-socket-end-drain.test.ts each fail on a single lane and pass on retry elsewhere

This diff only touches src/runtime/api/BunObject.rs (mmap_file), src/sys/lib.rs (mmap_file), and test/js/bun/util/mmap.test.js. Ready for review.

@Jarred-Sumner
Jarred-Sumner merged commit f5ba155 into main Jul 19, 2026
76 of 78 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the farm/de2993fd/fix-mmap-offset branch July 19, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants