Fix segfault inspecting JSX with circular props - #30585
Conversation
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
|
Duplicate of #30584 which is more complete: also fixes the same issue in |
There was a problem hiding this comment.
LGTM — minimal one-tag addition to the existing circular-ref guard, with regression tests.
Extended reasoning...
Overview
This PR fixes a segfault when Bun.inspect / console.log is called on a JSX element whose props (or children) reference the element itself. The fix is a single token addition in src/jsc/ConsoleObject.zig: .JSX is appended to the canHaveCircularReferences() switch arm alongside .Function, .Array, .Object, .Map, .Set, .Error, .Class, .Event. Two regression tests in test/js/bun/util/inspect.test.js cover circular props and circular children.
Security risks
None. This is a defensive change in the inspect/formatting path — it adds a stack-safety check and visited-map lookup for a tag that was previously skipping them. No auth, crypto, permissions, parsing of untrusted input, or external I/O is touched.
Level of scrutiny
Low. The mechanism (canHaveCircularReferences gating the visited-map + stack_check.isSafeToRecurse() block at ConsoleObject.zig:2092–2121) is already exercised by every Object/Array/Map inspect call; this just opts .JSX into the same well-trodden path. The .JSX printAs branch (line 3077+) clearly recurses via this.format for each prop and child, so the omission was an obvious oversight rather than intentional.
Other factors
- The change follows the established pattern exactly — no new logic, just one more enum value in the allowlist.
- Regression tests assert
[Circular]appears rather than snapshotting full output, so they're robust to formatting tweaks. Bun.markdown.reactis used elsewhere in the test suite (test/js/bun/md/md-react.test.ts), so it's a known-good way to construct a JSX-tagged value without a JSX transform.- No prior reviewer comments, no CODEOWNERS concerns, and the bug-hunting system found nothing.
What
Bun.inspect(andconsole.log) segfaulted on JSX/React elements whereprops(or any property other thanchildren) pointed back at the element itself, creating a circular reference.Repro
Root cause
The generic
printAspath guards against circular references by tracking visited objects in a map and by checking the stack budget — but only whenTag.canHaveCircularReferences()returnstruefor the current tag..JSXwas missing from that list, so inspecting a JSX element just recursed intothis.formatfor each prop with no bookkeeping. When a prop referenced the element itself, this ran until the native stack was exhausted.Fix
Add
.JSXtocanHaveCircularReferences(). The existing visited-map + stack-check code inprintAsthen handles JSX the same asObject,Array,Map, etc.: the second visit prints[Circular]instead of recursing.Added regression tests covering circular
propsand circularchildren.