Fix crash in Bun.inspect when JSX props is non-object or circular - #30555
Fix crash in Bun.inspect when JSX props is non-object or circular#30555robobun wants to merge 1 commit into
Conversation
Bun.inspect of a JSX-like element (object with $$typeof = react.element) assumed the `props` value was always an object, unwrapping it with `.?`. When it was a primitive, this panicked with a null unwrap. Additionally, the JSX formatter was not included in the set of tags that track visited objects, so a circular reference through `props` or `props.children` would recurse until the stack overflowed. - Skip props handling when `props` is not an object - Add .JSX to canHaveCircularReferences so the visited map and stack check apply to JSX elements
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ 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 (2)
Comment |
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
|
Closing as duplicate of #29709, which applies the same |
There was a problem hiding this comment.
LGTM — minimal, well-tested crash fix for fuzzer-found JSX inspect issues.
Extended reasoning...
Overview
This PR fixes two crashes in Bun.inspect / console.log when formatting JSX-shaped objects (objects with $$typeof set to a React element symbol). The Zig change in src/jsc/ConsoleObject.zig is two lines: (1) add .JSX to canHaveCircularReferences so the existing visited-map and isSafeToRecurse stack guard apply, and (2) replace an unsafe props.getObject().? unwrap with orelse break :props so a non-object props is treated as no props instead of panicking. Three regression tests are added to test/js/bun/util/inspect.test.js.
Security risks
None. This is purely output-formatting code in the inspector. The change makes the code strictly more defensive (replacing a null-unwrap panic and unbounded recursion with graceful handling). No auth, crypto, filesystem, or network surface is touched.
Level of scrutiny
Low. The diff is tiny and mechanical: adding one enum variant to an existing allowlist that gates well-established cycle/stack protection (lines 2092–2122), and swapping .? for orelse break :props on a labeled block. The defer this.quote_strings = prev_quote_strings is registered before the break, so state is correctly restored on early exit. Falling through to the closing /> after the block is the same path taken when props is absent, so <div /> is the expected output for the new test.
Other factors
The bugs were found by Fuzzilli, the PR includes targeted regression tests for all three scenarios (primitive props, el.props = el, el.props.children = el), and the author reports the full inspect.test.js suite plus console tests pass. No CODEOWNERS apply to these paths and there are no outstanding human review comments. The bug-hunting system found no issues.
What does this PR do?
Fixes two crashes in
Bun.inspect/console.logwhen formatting JSX-like elements (objects with$$typeofset to the React element symbol):Null unwrap panic — the formatter assumed
propswas always an object and unwrappedprops.getObject()with.?. Whenpropswas a primitive (e.g. a number), this panicked withattempt to use null value.Stack overflow — the
.JSXtag was not included incanHaveCircularReferences, so the visited-object map and theisSafeToRecursestack check were skipped. A circular reference reachable throughpropsorprops.childrenrecursed until the process segfaulted.Found by Fuzzilli (fingerprint
11b5374beaf7e44f).Repro
How did you verify your code works?
test/js/bun/util/inspect.test.jsbun bd test test/js/bun/util/inspect.test.js— all 75 tests passUSE_SYSTEM_BUN=1 bun test test/js/bun/util/inspect.test.js -t jsx— segfaults without the fixbun bd test test/js/bun/console/andtest/js/web/console/console-log.test.tspass