Bun.mmap: throw on non-object options instead of asserting#30404
Conversation
Bun.mmap(path, 256) hit a debug assertion in JSValue.get() because the options argument was passed through to getBooleanLoose without checking that it is an object. Validate the argument and throw ERR_INVALID_ARG_TYPE for non-object values; undefined and null are treated the same as omitted.
|
Updated 9:12 AM PT - May 8th, 2026
❌ @robobun, your commit 6418e2c has 3 failures in
🧪 To try this PR locally: bunx bun-pr 30404That installs a local version of the PR into your bun-30404 --bun |
There was a problem hiding this comment.
LGTM — straightforward input validation fix following the established pattern in this file.
Extended reasoning...
Overview
This PR fixes a fuzzer-found debug assertion in Bun.mmap() when a non-object value is passed as the second (options) argument. The fix wraps the existing options-parsing block in src/runtime/api/BunObject.zig with an opts.isObject() check, throws ERR_INVALID_ARG_TYPE for non-object/non-nullish values, and treats undefined/null as no options. A new test in test/js/bun/util/mmap.test.js covers number/string/boolean (throw) and undefined/null (no throw).
Security risks
None. This is purely input validation that converts a debug-build crash into a proper JS exception. No auth, crypto, permissions, or data exposure paths are touched. The actual mmap syscall path and its arguments are unchanged.
Level of scrutiny
Low. The diff is almost entirely re-indentation — the only behavioral additions are the isObject() guard and the else if (!opts.isUndefinedOrNull()) throw branch. This exact pattern is already used in the same file by which(), JSZlib.getOptions(), and JSZstd.getOptions(), so there's no novel design here.
Other factors
The bug hunting system found no issues. The change is self-contained to one function, has direct test coverage for all new branches, and was found via Fuzzilli (fingerprint referenced in the description). No outstanding reviewer comments.
|
All 4 failing shards are pre-existing flakes unrelated to this change (which only touches
The |
…0404) ## What does this PR do? `Bun.mmap(path, 256)` (or any non-object second argument) hit a debug assertion in `JSValue.get()` because the options value was passed straight to `getBooleanLoose` without first checking that it is an object. Now non-object, non-nullish values throw `ERR_INVALID_ARG_TYPE`, and `undefined`/`null` are treated the same as omitting the options argument. ``` panic(main thread): reached unreachable code bun.debugAssert jsc.JSValue.JSValue.get src/jsc/JSValue.zig:1534 jsc.JSValue.JSValue.getBooleanLoose src/jsc/JSValue.zig:1867 runtime.api.BunObject.mmapFile src/runtime/api/BunObject.zig:1219 ``` ## How did you verify your code works? Added a test to `test/js/bun/util/mmap.test.js` covering number/string/boolean (throw) and undefined/null (no throw). Found by Fuzzilli (fingerprint `b1832bde6df73226`). --- Co-authored-by: Alistair Smith <hi@alistair.sh> Signed-off-by: Sisyphus <sisyphus@ohos-bun.dev>
What does this PR do?
Bun.mmap(path, 256)(or any non-object second argument) hit a debug assertion inJSValue.get()because the options value was passed straight togetBooleanLoosewithout first checking that it is an object.Now non-object, non-nullish values throw
ERR_INVALID_ARG_TYPE, andundefined/nullare treated the same as omitting the options argument.How did you verify your code works?
Added a test to
test/js/bun/util/mmap.test.jscovering number/string/boolean (throw) and undefined/null (no throw).Found by Fuzzilli (fingerprint
b1832bde6df73226).