Bump WebKit (oven-sh/WebKit#691 preview): restore the Vector capacity that WebKit 310668@main halved - #42982
Bump WebKit (oven-sh/WebKit#691 preview): restore the Vector capacity that WebKit 310668@main halved#42982robobun wants to merge 2 commits into
Conversation
|
Updated 3:42 AM PT - Sep 17th, 2026
✅ @robobun, your commit ab0a5e225a5b4ca8fb2e9ccf9c1ec7e4afee8a9d passed in 🧪 To try this PR locally: bunx bun-pr 42982That installs a local version of the PR into your bun-42982 --bun |
|
Status: reproduced on a release build of main ( require("node:url").fileURLToPath("file:///%E4%B8%80" + "q".repeat(2 ** 30 - 1));The process exits 134 with The engine fix is oven-sh/WebKit#691. This PR pins its preview build, updates This PR is a draft until oven-sh/WebKit#691 merges. Then the pin moves to the |
…de no longer aborts the process String::fromUTF8 sized its UTF-16 buffer with a Vector constructor that calls CRASH() past 2^30 - 1 code units. WTF::URL::fileSystemPath() decodes the path of a file: URL through it, so fileURLToPath(), the fs functions that take a URL, import(), require(), new Worker() and process.dlopen() aborted on a decoded path of 2^30 bytes that is not all ASCII. The preview build makes the conversion return a null string, which these callers already get for a path that is not UTF-8.
…ity from before WebKit 310668@main The abort is a regression in Bun 1.3.13. WebKit 310668@main took the high bit of Vector's element count for a borrow bit, but halved the limit on the size in bytes, so every Vector whose element is wider than a byte lost half of its capacity. oven-sh/WebKit#691 limits the count instead. fileURLToPath() returns the 2^30 byte path again, as Bun 1.3.12 does, and the test now expects that path and not "". VectorSizeLimit.h states the WebKit formula in two static_asserts, so it moves with the pin.
|
Reworked in ab0a5e2: this PR moved from oven-sh/WebKit#683 to oven-sh/WebKit#691. oven-sh/WebKit#683 made |
1b59332 to
ab0a5e2
Compare
Problem
WTF::Vectorwhose element is wider than a byte needs more than 2^31 - 1 bytes:panic(main thread): abort() called, exit 134, also insidetry/catch. Five scripts are in Notes. One isrequire("node:url").fileURLToPath("file:///%E4%B8%80" + "q".repeat(2 ** 30 - 1)), which ends inStringImpl::create(StringImpl.cpp:289).Vector's element count for a borrow bit, butisValidCapacityForVector(Vector.h:212) halved the limit on the size in bytes. AVector<char16_t>went from 2^31 - 1 to 2^30 - 1 elements.Fix
min(UINT_MAX / sizeof(T), UINT_MAX >> 1). It admits only capacities that shipped before 310668@main. This PR pins its preview build (the current pin plus that commit). It is a draft until [WTF] Vector: limit the capacity by the element count, not by half the size in bytes (regression from 310668@main) WebKit#691 lands. Then the pin moves to the merge commit.VectorSizeLimit.hstates the WebKit formula in twostatic_asserts, so it changes with the pin.test/js/bun/util/fileUrl.test.jsexits 134 on a release build of main and passes with the pin. All five scripts give the 1.3.12 result on a release build with the pin, and two of them also ran clean on the debug ASAN build (Notes).Background
isValidCapacityForVector<T>(n)guards eachVectorbuffer allocation. The crashing path callsCRASH().String::fromUTF8and other converters size aVector<char16_t>by the length of their input, so this limit decides how long a string they accept.scripts/build/deps/webkit.ts. A WebKit pull request publishes a preview build asautobuild-preview-pr-<n>-<sha8>.Notes
Origin. A fuzzing run found the aborts one by one. No user reported them. 310668@main is "Support CanBorrow in Vector" (webkit.org/b/311221, 2026-04-06). Its message says that the maximum capacity is now 2^31 - 1, which is the count. The formula it changed limits the bytes.
Regression table. Linux x64 release builds. "this PR" is a release build of this branch.
url.fileURLToPath("file:///%E4%B8%80" + "q".repeat(2 ** 30 - 1)).length("\ud800" + "q".repeat(2 ** 30)).toWellFormed().lengthfor (let i = 0; i < 33554431; i++) queueMicrotask(f)new URLSearchParams("a=" + "\u4e00".repeat(2 ** 29)).get("a").lengthu = new URL("http://a/"); u.host = "q".repeat(2 ** 30); u.host.lengthconsole.count("q".repeat(2 ** 30))buffer.transcode(new Uint8Array(2 ** 30), "latin1", "ucs2")The two rows that stay. Both need a
Vectorof bytes with 2^31 elements. The borrow bit leaves 31 bits for the count, so 2^31 - 1 is the limit for a one-byte element and no formula gives that back.console.countconverts throughStringImpl::tryGetUTF8ForCharacters, which asks for two bytes for each Latin-1 character (#42868).transcodegrows its result inNodeBufferModule.cpp:220(#42875).Debug ASAN build with the pin. The
queueMicrotaskscript runs in 215 s and thetoWellFormedscript in 12 s, both with exit 0 and nothing on stderr. The other three take several minutes each there and I did not run them.The test. It runs the first script in a child and expects the length, the first five characters and the last two. It takes 8.3 s and the child peaks at 7 GiB, so it needs 12 GiB and has a 60 s timeout. A debug build takes about 7 minutes to parse a URL of that size, so debug and ASAN builds skip it.
VectorSizeLimit.his the check that every build runs: its twostatic_asserts fail to compile if the WebKit formula and Bun's copy differ. For the same reason this branch does not compile withsrc/from main: the oldstatic_asserts reject the new formula.Suites.
bun bd testwith the pin:fileUrl.test.js,wrapAnsi.test.ts,streams-string-limit.test.ts,url-fileurltopath.test.js,url.test.ts(307 pass, 1 skip, 0 fail). Release build with the pin: the same plusstreams.test.js. These are the users ofmaxVectorSizeandmaxDequeSize.Other open pull requests.
String::fromUTF8, sofileURLToPathreturned"". With [WTF] Vector: limit the capacity by the element count, not by half the size in bytes (regression from 310668@main) WebKit#691 the script gets its correct path, and no input reaches that path. [WTF] String::fromUTF8 returns a null string when its UTF-16 buffer cannot be allocated WebKit#683 is a draft now, and I close it when [WTF] Vector: limit the capacity by the element count, not by half the size in bytes (regression from 310668@main) WebKit#691 lands.url.hostscript), JSC builtins: throw instead of aborting when a script-sized Vector cannot grow (WebKit bump for oven-sh/WebKit#666) #42897, Throw a RangeError instead of aborting when require.resolve paths or Worker preload outgrows its Vector #42735, url: throw a RangeError instead of aborting when URLSearchParams or FormData outgrows its Vector #40577 and others turn aborts at this limit into errors. Those errors still apply past the restored limit. The inputs that reach them are twice as large.no test proof · iteration 0 · platform-specific test(s) that do not run on this machine, deferring to CI, which covers all platforms: test/js/bun/util/fileUrl.test.js