Skip to content

Fix stack overflow in Bun.inspect with circular JSX elements - #30584

Closed
robobun wants to merge 2 commits into
mainfrom
farm/301da87b/fix-jsx-circular-inspect
Closed

Fix stack overflow in Bun.inspect with circular JSX elements#30584
robobun wants to merge 2 commits into
mainfrom
farm/301da87b/fix-jsx-circular-inspect

Conversation

@robobun

@robobun robobun commented May 12, 2026

Copy link
Copy Markdown
Collaborator

Bun.inspect() / console.log() crashed with a stack overflow when given a React element that referenced itself via key, props, or children.

const el = {
  $$typeof: Symbol.for("react.element"),
  type: "div",
  props: {},
};
el.props.foo = el;
Bun.inspect(el); // SIGSEGV

The JSX branch of the formatter recursively prints key, each prop value, and children, but .JSX was missing from canHaveCircularReferences() so it skipped both the visited-map check and the isSafeToRecurse() stack guard. Any cycle through a JSX element recursed until the stack blew out.

Fix: include .JSX in canHaveCircularReferences() in both ConsoleObject.zig and pretty_format.zig so cycles print as [Circular].

Also replaced props.getObject().? with props.getObject() orelse break :props — the "JSX props are always objects" assumption is not true for arbitrary objects shaped like React elements, and unwrapping panicked on props: 123.

Found by Fuzzilli.

The JSX formatter did not participate in circular reference detection
because .JSX was missing from canHaveCircularReferences(). A React
element that referenced itself via key, props, or children would
recurse until the stack overflowed.

Also guard against a non-object props value instead of unwrapping
getObject() unconditionally.
@robobun

robobun commented May 12, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 3:14 PM PT - May 12th, 2026

@robobun, your commit 3020b0c has 1 failures in Build #53857 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 30584

That installs a local version of the PR into your bun-30584 executable, so you can run:

bun-30584 --bun

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d05a5b8-d9a1-43ac-ad14-9b5c2bacf6bf

📥 Commits

Reviewing files that changed from the base of the PR and between 6fb6fdc and 3020b0c.

📒 Files selected for processing (1)
  • test/js/bun/util/inspect.test.js

Walkthrough

This PR extends JSX element inspection to safely handle circular references. The formatters now recognize JSX as a type that can contain circular data, and both formatters defensively extract the props field to handle cases where props is not an object. Test coverage validates circular-reference detection across various JSX structures.

Changes

JSX Circular Reference Handling

Layer / File(s) Summary
Circular-reference eligibility for JSX
src/jsc/ConsoleObject.zig, src/test_runner/pretty_format.zig
.JSX tag is added to canHaveCircularReferences in both ConsoleObject and JestPrettyFormat formatters, enabling circular-reference tracking for JSX elements.
Defensive props extraction in JSX formatters
src/jsc/ConsoleObject.zig, src/test_runner/pretty_format.zig
Props extraction changes from unconditional unwrap to guarded conversion using props.getObject() orelse break, preventing failures when props is not an object.
Test cases for JSX circular references
test/js/bun/util/inspect.test.js
Five test cases verify circular-reference detection when the circular value appears in props, when props itself is circular, when circular data is in the element key, when circular data is in children, and when props is a non-object.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix stack overflow in Bun.inspect with circular JSX elements' directly and clearly summarizes the main change in the PR—it identifies the specific problem (stack overflow), the feature affected (Bun.inspect), and the root cause (circular JSX elements).
Description check ✅ Passed The PR description covers both required template sections: it explains what the PR does (fixes stack overflow in JSX circular reference handling) and how it was verified (test cases added, issue discovered by Fuzzilli), though verification could be more explicit.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/js/bun/util/inspect.test.js`:
- Around line 329-339: The test "jsx with circular reference as props object"
currently only asserts Bun.inspect(el) contains "[Circular]"; tighten it by also
asserting the JSX-format is preserved—e.g., check that the inspected output
begins with "<div" or otherwise contains the JSX-like opening tag for the
element type. Update the expectation in the test (the it block where el is
created with $$typeof Symbol.for("react.transitional.element") and props
circular reference) to include a second assertion that verifies the output's JSX
shape (startsWith "<div" or contains "<div") alongside the existing Circular
assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 30e7b424-7335-4eb5-957c-e34d653a6cc6

📥 Commits

Reviewing files that changed from the base of the PR and between 39540fd and 6fb6fdc.

📒 Files selected for processing (3)
  • src/jsc/ConsoleObject.zig
  • src/test_runner/pretty_format.zig
  • test/js/bun/util/inspect.test.js

Comment thread test/js/bun/util/inspect.test.js
@github-actions

Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. console: guard JSX/Proxy recursion in Bun.inspect (stack overflow SIGSEGV) #29709 - Same fix: adds .JSX to canHaveCircularReferences() and replaces unsafe props.getObject().? with orelse break :props in both ConsoleObject.zig and pretty_format.zig
  2. Fix stack overflow in Bun.inspect for circular JSX elements #30126 - Adds .JSX to canHaveCircularReferences() in the same two files (without the props.getObject() safety fix)

🤖 Generated with Claude Code

@robobun

robobun commented May 12, 2026

Copy link
Copy Markdown
Collaborator Author

Duplicate of #29709 which has the same fix with more thorough tests.

@robobun robobun closed this May 12, 2026
@robobun
robobun deleted the farm/301da87b/fix-jsx-circular-inspect branch May 12, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant