Repository navigation
Conversation
get_stringish() returns a bun_core::String carrying a +1 WTFStringImpl
ref. The 'hostname' branch wraps it in OwnedString for RAII deref, but
the 'unix' branch did not, leaking one StringImpl per Bun.serve({unix})
or server.reload({unix}) call. Matches the Zig reference's
'defer unix.deref()'.
|
Repro: RSS grows ~1:1 with PR: #32287 The diff is green: 282 CI jobs passed across Linux x64/aarch64/musl/ASAN, Windows, macOS x64, FreeBSD. The new test passed on every lane that ran it, including x64-asan. Remaining red is unrelated infrastructure:
Ready for a maintainer to merge. |
|
Warning Review limit reached
More reviews will be available in 7 minutes and 14 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
|
Updated 6:47 AM PT - Jun 15th, 2026
❌ @robobun, your commit d44ac3f has 2 failures in
🧪 To try this PR locally: bunx bun-pr 32287That installs a local version of the PR into your bun-32287 --bun |
There was a problem hiding this comment.
LGTM — one-line fix mirroring the hostname branch directly above; the ASAN-threshold nit on the test is worth addressing but doesn't block.
Extended reasoning...
Overview
This PR adds a single line to ServerConfig::from_js in src/runtime/server/ServerConfig.rs: wrapping the bun_core::String returned by get_stringish(global, "unix") in bun_core::OwnedString so its Drop impl releases the +1 WTFStringImpl ref at scope exit. It also adds an RSS-delta leak regression test to bun-serve-args.test.ts.
The fix is mechanically identical to the hostname branch ~15 lines above (let host = bun_core::OwnedString::new(host);). I verified that OwnedString is #[repr(transparent)] over String with Deref<Target = String> (so unix.to_utf8() still resolves) and Drop calling self.0.deref() — exactly the RAII the PR description claims. The shadowing let unix = ... is intentional and matches house style.
Security risks
None. This is a refcount-release fix on an argument-parsing path; no auth, crypto, or permission surface is touched. The only behavioral change is that a WTFStringImpl is now freed instead of leaked.
Level of scrutiny
Low. A one-line change applying an established in-file pattern, with a clear repro and before/after RSS measurements in the PR description. The Rust change cannot introduce a use-after-free because the bytes are duped into a ZBox before unix drops, and OwnedString's Deref keeps to_utf8() working unchanged.
Other factors
The bug-hunting system flagged one nit: the new test's expect(deltaMB).toBeLessThan(64) lacks the isASAN ? … : 64 widening used by sibling leak tests in the same directory. That's a fair point about potential ASAN-lane flakiness and is posted inline; it's test-only and doesn't affect the correctness of the fix, so I'm approving while leaving the nit for the author to address.
Match house convention for RSS-delta leak tests in this directory. Bumped string size to 512KB so the leak signature (~500MB) stays well above the widened ASAN threshold (192MB).
There was a problem hiding this comment.
LGTM — the one-line OwnedString wrap mirrors the hostname branch exactly; the remaining ASAN-threshold nit is a test-tuning follow-up, not a blocker.
Extended reasoning...
Overview
One-line production fix in src/runtime/server/ServerConfig.rs: wrap the bun_core::String returned by get_stringish(global, "unix") in bun_core::OwnedString::new() so its WTFStringImpl ref is released on scope exit. This is a copy of the pattern used by the hostname branch ~15 lines above and matches the Zig reference's defer unix.deref(). The accompanying test in bun-serve-args.test.ts drives the hostname+unix error path with a 512KB string and asserts bounded RSS growth.
Security risks
None. No new inputs, parsing, auth, or external surface. The change only adds an RAII wrapper around an existing local; control flow and the value passed to ZBox::from_bytes are unchanged.
Level of scrutiny
Low for the Rust change: it is mechanical, pattern-matched against adjacent code, and verified by before/after RSS measurements (~258MB → ~22MB). Low-medium for the test: RSS-threshold leak tests are inherently tunable and the ASAN constant may need one more bump, but that is a CI-calibration concern, not a correctness concern.
Other factors
I previously flagged the missing ASAN guard; the author addressed it in a30f693 by adding isASAN ? 192 : 64. The new inline nit observes that 192 may still sit below the quarantine-fill ceiling for 512KB strings and suggests 400 (matching neighboring tests) or quarantine_size_mb=0. That's a reasonable follow-up but speculative (no observed CI failure yet) and trivially fixable if it flakes — not worth holding a one-line leak fix over. Approving with the nit attached.
There was a problem hiding this comment.
LGTM — one-line OwnedString wrap matching the hostname branch directly above; the ASAN threshold discussion is resolved by the empirical x64-asan pass.
Extended reasoning...
Overview
The production change is a single line in src/runtime/server/ServerConfig.rs: wrapping the bun_core::String returned by get_stringish(global, "unix") in bun_core::OwnedString so its Drop releases the +1 WTFStringImpl ref. This is a verbatim copy of the pattern used ~15 lines above for the hostname branch (let host = bun_core::OwnedString::new(host)), and mirrors the Zig reference's defer unix.deref(). The accompanying change in bun-serve-args.test.ts adds a subprocess RSS-delta regression test plus the harness imports it needs.
Security risks
None. The change adds RAII cleanup for a string ref on an option-parsing path; it does not touch auth, crypto, permissions, request handling, or any externally-reachable surface beyond what already existed. The only behavioral effect is that a previously-leaked refcount is now released.
Level of scrutiny
Low. The fix is mechanical and pattern-matched against adjacent, already-shipping code in the same function. OwnedString is the documented owner wrapper for the Copy/no-Drop bun_core::String; there is no plausible way for this wrap to introduce a use-after-free since unix_str (the to_utf8() borrow) and the ZBox::from_bytes copy both complete before unix drops at scope end. The test follows the repo's standard RSS-leak-test shape (subprocess via bunExe()/bunEnv, warmup, GC, delta assertion with an isASAN widen).
Other factors
I previously raised two nits about the ASAN threshold; both threads are resolved. On the second, the author rebutted my quarantine arithmetic with the correct observation that WTFStringImpl goes through bmalloc/libpas (not ASAN-intercepted malloc), measured ~22MB under ASAN across 5 local runs, and confirmed the test passed on the x64-asan CI lane in build 62425 with the 192MB threshold — that's empirical evidence over my theoretical model, and 192MB is ~8× headroom over observed while staying well below the ~500MB leak signature. The musl LTO link failures in build 62412 are an unrelated bitcode/data-layout infrastructure issue (the change adds no symbols and cannot affect linking); CI was retriggered. The bug-hunting system found nothing. No CODEOWNERS cover these paths.
|
Closing: #40238 made Verified: the "unix option does not leak the string" test from this branch fails on a debug build from before #40238 (RSS delta 516 MB) and passes on current main (4441116) with no change to |
What
get_stringish()returns abun_core::Stringcarrying a +1WTFStringImplref (viato_bun_string).bun_core::Stringis#[derive(Copy)]and has noDropimpl by design; callers must wrap it inOwnedStringfor scope-exitderef().The
hostnamebranch inServerConfig::from_jsalready does this. Theunixbranch did not, so everyBun.serve({ unix: ... })andserver.reload({ unix: ... })leaked oneWTFStringImpl. The Zig reference (ServerConfig.zig:810) has the explicitdefer unix.deref().Repro
Drive the hostname+unix error path so no server is actually created:
RSS growth scales 1:1 with the
unixstring size per call.Fix
Wrap the returned string in
bun_core::OwnedString, matching thehostnamebranch directly above.Verification
bun-serve-args.test.ts: 47 pass, 1 todo (pre-existing).