Skip to content

jsc: don't leak builtin @-identifiers in TypeError messages (debug/ASAN) - #36262

Open
robobun wants to merge 3 commits into
mainfrom
farm/57165bac/fix-iterator-from-error-message-leak
Open

jsc: don't leak builtin @-identifiers in TypeError messages (debug/ASAN)#36262
robobun wants to merge 3 commits into
mainfrom
farm/57165bac/fix-iterator-from-error-message-leak

Conversation

@robobun

@robobun robobun commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

What

Bumps WebKit to a preview build containing oven-sh/WebKit#369 (the current WEBKIT_VERSION 549170099 plus one commit) and adds a regression test.

Why

In ASSERT_ENABLED builds (debug and ASAN), JSC builtins emit expression info. When a .@call() inside a builtin hits a non-callable value, the Call IC slow path (throwNotAFunctionErrorFromCallIC in RepatchInlines.h) passes the builtin code block and bytecode index straight into appendSourceToErrorMessage, which splices the private @-identifier source text into the user-visible TypeError message.

Release builds are unaffected because BytecodeGenerator::emitExpressionInfo skips builtins under #if !ASSERT_ENABLED, so hasExpressionInfo() returns false and the append step bails early.

Repro

const t = (l, f) => { try { f(); } catch (e) { console.log(l, String(e)); } };
t("A", () => Iterator.from({}).next());
t("C", () => Iterator.from({ next: () => ({ done: false, value: 1 }), return: 5 }).return());

debug/ASAN before:

A TypeError: @getWrapForValidIteratorInternalField(this, @wrapForValidIteratorFieldIteratedNextMethod).@call is not a function. (In '@getWrapForValidIteratorInternalField(this, @wrapForValidIteratorFieldIteratedNextMethod).@call(@getWrapForValidIteratorInternalField(this, @wrapForValidIteratorFieldIteratedIterator))', '@getWrapForValidIteratorInternalField(this, @wrapForValidIteratorFieldIteratedNextMethod).@call' is undefined)
C TypeError: returnMethod.@call is not a function. (In 'returnMethod.@call(iterator)', 'returnMethod.@call' is 5)

after (matches release output):

A TypeError: undefined is not a function
C TypeError: 5 is not a function

Also covers Iterator.from({[Symbol.iterator]: 5}) (getIteratorFlattenable) and any other builtin that reaches the Call IC slow path with a non-callable.

Verification

Built WebKit from source with the fix applied; test/js/bun/jsc/builtin-error-message.test.ts fails under a debug build without the WebKit change and passes with it. Release builds pass either way (they never had the leak).

Notes

Draft until the WebKit preview build (autobuild-preview-pr-369-bce3c3e1) finishes publishing; CI will fail fetching WebKit until then. Once oven-sh/WebKit#369 merges, WEBKIT_VERSION should be set to the resulting main sha rather than the preview tag.


[decide:webkit] gate passed · iteration 1 · 2 files touched

passes on PR (with fix)
Test-only change.

Debug/ASAN (expected pass):
$ bun bd test 'test/js/bun/jsc/builtin-error-message.test.ts'
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/js/bun/jsc/builtin-error-message.test.ts
bun test v1.4.0 (6e52dfd22)

test/js/bun/jsc/builtin-error-message.test.ts:
(pass) %WrapForValidIteratorPrototype%.next on a wrapped iterator with no next method [17.14ms]
(pass) %WrapForValidIteratorPrototype%.return with a non-callable return [7.66ms]
(pass) Iterator.from with a non-callable Symbol.iterator [5.68ms]

 3 pass
 0 fail
 9 expect() calls
Ran 3 tests across 1 file. [2.58s]
Exit: 0
diff hotspot
scripts/build/deps/webkit.ts                  |  2 +-
 test/js/bun/jsc/builtin-error-message.test.ts | 37 +++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

gate history · 1 passed · 1 rejected · iteration 1

evidence per changed file
file                                           reads  edits  tests
scripts/build/deps/webkit.ts                       9      6      0
test/js/bun/jsc/builtin-error-message.test.ts      0      1      0

In ASSERT_ENABLED builds (debug and ASAN), JSC builtins emit expression
info, and when a .@call() inside a builtin (e.g. the WrapForValidIterator
next/return prototype functions used by Iterator.from) hits a non-callable
value, the Call IC slow path feeds the builtin code block and bytecode
index straight into appendSourceToErrorMessage, which splices the private
@-identifier source text into the user-visible TypeError:

    Iterator.from({}).next()
    // TypeError: @getWrapForValidIteratorInternalField(this,
    //   @wrapForValidIteratorFieldIteratedNextMethod).@call is not a
    //   function. (In '...')

Release builds are unaffected: BytecodeGenerator::emitExpressionInfo skips
builtins under '#if !ASSERT_ENABLED', so hasExpressionInfo() returns false
and appendSourceToErrorMessage bails early.

WebKit fix (oven-sh/WebKit#369) adds an isBuiltinFunction() check in
appendSourceToErrorMessage so ASSERT_ENABLED output matches release. The
preview build here is the current WEBKIT_VERSION (549170099) plus that one
commit.
@robobun

robobun commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 8:15 PM PT - Jul 28th, 2026

@robobun, your commit 6e52dfd has some failures in Build #84438 (All Failures)


🧪   To try this PR locally:

bunx bun-pr 36262

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

bun-36262 --bun

@robobun
robobun marked this pull request as ready for review July 28, 2026 22:43
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 17 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8a848bef-3007-49c4-97d5-446910e05bb7

📥 Commits

Reviewing files that changed from the base of the PR and between e532ad9 and 6e52dfd.

📒 Files selected for processing (2)
  • scripts/build/deps/webkit.ts
  • test/js/bun/jsc/builtin-error-message.test.ts

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

@claude claude 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.

No issues found in the diff, but this bumps WEBKIT_VERSION to a preview-PR tag rather than a merged main sha — per the PR description, that's intentionally temporary pending oven-sh/WebKit#369 landing. A human should decide whether to merge on the preview build or wait for the main sha.

Checked: prebuiltUrl/prebuiltDestDir already handle the autobuild- prefix correctly (tag passed through, full string used as cache key). The new test asserts exact messages (toBe) plus negative @-leak checks across three builtin call-IC paths.

Extended reasoning...

Overview

Two changes: (1) scripts/build/deps/webkit.ts swaps WEBKIT_VERSION from commit sha 549170099... to preview tag autobuild-preview-pr-369-bce3c3e1, and (2) adds test/js/bun/jsc/builtin-error-message.test.ts covering three JSC-builtin TypeError paths that previously leaked @-prefixed private identifiers into user-visible messages under ASSERT_ENABLED (debug/ASAN) builds.

Security risks

None. The change affects error-message text formatting inside JSC and a build-script version constant; no auth, crypto, permissions, or untrusted-input parsing paths.

Level of scrutiny

High — not because the Bun-side diff is complex (it's a one-line version bump plus a small test), but because any WebKit bump swaps the JS engine binary for every platform/profile. The actual behavioral fix lives in oven-sh/WebKit#369, which isn't reviewable from this repo. The PR author explicitly flags the preview tag as temporary and says it should be replaced with the resulting main sha once the WebKit PR merges. That's a merge-timing/process decision a maintainer should make.

Other factors

  • The build-script side is safe: prebuiltUrl already special-cases version.startsWith("autobuild-") to avoid double-prefixing the release tag, and prebuiltDestDir uses the full tag (minus the autobuild- prefix) as the cache-dir key, so there's no collision with the previous sha-keyed extraction.
  • The test file follows repo conventions: exact-value assertions (toBe), covers three sibling entry points to the same Call IC slow path, and the not.toContain("@") / not.toContain("WrapForValidIterator") checks make the failure mode obvious if it regresses. It correctly lives under test/js/bun/jsc/.
  • No prior claude[bot] review on this PR; nothing to avoid duplicating.

@robobun

robobun commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator Author

The preview tag is temporary as described; oven-sh/WebKit#369 is the one-commit diff (based on the current WEBKIT_VERSION 549170099, so this bump pulls in only that fix). Once it merges I'll update WEBKIT_VERSION to the resulting main sha here.

CI status: build #84438 built the preview WebKit cleanly on every lane and test/js/bun/jsc/builtin-error-message.test.ts passed everywhere. All 12 reported failures are tagged [flaky] (parallel-batch races that passed on retry) in unrelated areas (autoinstall, MySQL timeout, napi, svelte, net unix-socket, spawn chunk count); none touch JSC error messages or any file in this diff. Ready for a maintainer to merge oven-sh/WebKit#369 and swap the preview tag here for the resulting main sha.

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.

2 participants