Fix missing exception check when coercing Bun.plugin target to a string#32106
Conversation
When the target property's toString coercion throws (for example a Symbol.toPrimitive that returns an object), toStringOrNull returns null with the exception left pending. setupBunPlugin ignored the null and continued into object construction and the setup() call, tripping assertNoException() in debug builds. Propagate the exception with RETURN_IF_EXCEPTION after both the coercion and the rope resolution, matching the rest of the file.
|
Updated 3:13 AM PT - Jun 11th, 2026
✅ @robobun, your commit 0722034da4334925ae7c6b6a3dfc22ff3ec8cfdd passed in 🧪 To try this PR locally: bunx bun-pr 32106That installs a local version of the PR into your bun-32106 --bun |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughRefactors ChangesPlugin target option validation
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
|
Confirmed: #31286 was an earlier PR for the same bug (as were #28369 and #31017, both closed unmerged). None of them landed, which is why the fuzzer keeps rediscovering this crash. I closed #31286 since its base was months stale with a fully red build, and folded its test case (a target whose toString throws) into this PR alongside the Symbol.toPrimitive repro, so this PR supersedes it with no lost coverage. |
What does this PR do?
Fixes a debug assertion failure (
ASSERTION FAILED: Unexpected exception observed/assertNoException()) found by fuzzing, fingerprint99e6ccd6698f2a64.Repro:
On a debug build this aborts with SIGABRT instead of throwing.
Root cause: in
setupBunPlugin(src/jsc/bindings/BunPlugin.cpp), thetargetproperty is coerced withJSValue::toStringOrNull, which can run user JS (Symbol.toPrimitive,toString). Per the JSC header,toStringOrNullreturns null exactly when an exception was thrown, so the oldif (auto* targetJSString = ...)silently skipped validation and continued into builder-object construction and thesetup()call with the exception still pending on the VM. Debug builds tripassertNoException()at the next VM entry.The fix adds
RETURN_IF_EXCEPTIONafter the coercion and afterJSString::value(rope resolution can also throw), matching the pattern the rest of the file already uses. The thrown error now propagates to theBun.plugin()caller andsetup()is not invoked.How did you verify your code works?
test/js/bun/plugin/plugins.test.tsnext to the existing invalid-target test. It asserts the coercion error propagates and thatsetupis not called. On an unfixed debug build the test aborts with the assertion (exit 134); with the fix it passes. Release builds do not compile the assertion, so the crash is only observable on debug/ASAN builds.TypeError: Symbol.toPrimitive returned an object(exit 1), also clean underBUN_JSC_validateExceptionChecks=1.plugins.test.tssuite passes with the fix (30 pass, 1 todo, 0 fail), including the existing valid and invalidtargetcases.