Fix crash in Bun.inspect when Proxy getPrototypeOf trap throws#30240
Fix crash in Bun.inspect when Proxy getPrototypeOf trap throws#30240robobun wants to merge 1 commit into
Conversation
When walking the prototype chain during property enumeration, JSObject::getPrototype() can invoke a Proxy getPrototypeOf trap which may throw. In that case it returns an empty JSValue, and calling .getObject() on it dereferences a null cell pointer. Check for the empty value before calling getObject(), matching the existing handling in the fast-path branch of the same function. Apply the same fix to napi_get_all_property_names which has the identical pattern.
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
Review rate limit: 0/5 reviews remaining, refill in 2 minutes. Comment |
|
Updated 7:33 AM PT - May 4th, 2026
❌ @robobun, your commit cd520b3 has 1 failures in
🧪 To try this PR locally: bunx bun-pr 30240That installs a local version of the PR into your bun-30240 --bun |
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
There was a problem hiding this comment.
LGTM — minimal null-check + exception handling for throwing Proxy getPrototypeOf traps, with regression tests.
Extended reasoning...
Overview
This PR fixes a Fuzzilli-discovered null-pointer-dereference crash in two prototype-chain walks: JSC__JSValue__forEachPropertyImpl in bindings.cpp (the slow path used by Bun.inspect/console.log) and napi_get_all_property_names in napi.cpp. In both, JSObject::getPrototype() can invoke a Proxy getPrototypeOf trap; if the trap throws, an empty JSValue is returned and the previous code unconditionally called .getObject() on it. The fix stores the result, handles the pending exception (CLEAR_IF_EXCEPTION for inspect, NAPI_RETURN_IF_EXCEPTION for N-API), and null-checks before dereferencing. Two regression cases are added to the existing "crash testing" fixture in inspect.test.js.
Security risks
None. This is purely defensive error handling — it converts a hard crash into graceful termination of the prototype walk (inspect) or a propagated pending-exception status (N-API). No new user-controlled data flows, auth, or privilege boundaries are touched.
Level of scrutiny
Low. The change is ~6 lines of C++ across two sites, each a localized null/exception guard. It mirrors the existing fast-path handling in the same function (bindings.cpp:5250, 5327), which already uses if (JSValue proto = ...) to guard against empty returns, and uses the standard NAPI_RETURN_IF_EXCEPTION macro idiom in napi.cpp. The behavior choice (swallow the exception in inspect, propagate in N-API) is consistent with how each function already treats exceptions elsewhere in its body.
Other factors
- No CODEOWNERS apply to the modified files.
- The bug-hunting system found no issues.
- Regression tests are added to the existing crash-test fixture loop, so they're verified not to crash rather than asserting specific output — appropriate for a Fuzzilli fix.
- No prior human or bot reviews to address.
What does this PR do?
Fixes a null pointer dereference crash found by Fuzzilli in
Bun.inspect/console.logwhen printing an object whose prototype chain contains a Proxy with a throwinggetPrototypeOftrap.When walking the prototype chain in the slow path of
forEachProperty,JSObject::getPrototype()invokes the ProxygetPrototypeOftrap. If the trap throws,getPrototype()returns an emptyJSValue, and calling.getObject()on it dereferences a null cell pointer.The fix checks for an empty return value before calling
.getObject()and clears the exception, matching the existing handling in the fast-path branch of the same function.Also applies the same fix to
napi_get_all_property_nameswhich has the identical pattern.How did you verify your code works?
Added regression tests to
test/js/bun/util/inspect.test.jsthat crash before this change and pass after.