Skip to content

[YARR] Fail the path, not the pattern, when it needs more input than a string can hold - #864

Open
robobun wants to merge 4 commits into
mainfrom
robobun/66f8c8b4/regexp-required-input-beyond-string-length
Open

robobun wants to merge 4 commits into
mainfrom
robobun/66f8c8b4/regexp-required-input-beyond-string-length

Conversation

@robobun

@robobun robobun commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Replaces the length commit 692d32d of #835. To decide: remove this error (this PR), or report it at creation (#835).

Problem

  • Since Bun 1.4.0 one RegExp gives two answers. /(?:a|b*)+?c(?<!(?<=(?<=x{2147483647})y{2147483647})z{2147483647})/ answers test("ac") with true. After test("c") the same call throws SyntaxError: Invalid regular expression: pattern exceeds string length limits, and so does new RegExp of that text.
  • Cause: setupAlternativeOffsets (yarr/YarrPattern.cpp:2184) and ByteCompiler::emitDisjunction (yarr/YarrInterpreter.cpp:2781) refuse the pattern when a checked 32-bit input offset overflows. In V8 /c|a{4294967295}b/.exec("c") is ["c"].
  • A fuzz probe found this, no user did.

Fix

  • An overflow means that one path needs more input than a string can hold. Both functions now fail that path and keep the pattern, one commit each.
  • Verified: JSTests/stress/regexp-required-input-beyond-string-length.js fails on main. Also the regexp stress tests, test262 RegExp and a differential fuzz against node.
  • [JSC] Fix Yarr JIT abort when nested alternatives claim more than INT_MAX characters #862's test ran JIT-only: the interpreter threw this error for 6 of its 13 rows. Now it runs in every mode.

Background

  • setupAlternativeOffsets gives each term an input offset. emitDisjunction sums the input each alternative needs. A string holds at most 2^31 - 1 code units.
  • Considered: report the limit at creation (refuses more valid patterns), or drop the failed cell from RegExpCache (the match still throws).

Downsides

  • Behaviour change: these patterns were SyntaxErrors. Six upstream test files pin that and change (JSTests/BUN-TEST-DIFFERENCES.md, A10).
  • +4.6 instructions (+0.13%) per byte compile of an ordinary pattern. Nothing for pattern build, creation and match.
  • Still unlike V8: a minimum of 2^64 - 1 or more is refused, and an abandoned search reports no match ([JSC] A RegExp search that Yarr abandons throws a RangeError #343).
Notes

Relation to #835, #862, oven-sh/bun#46098 and oven-sh/bun#46347

What changes for a user

main this PR node v26.3.0
the RegExp of the first Problem bullet: test("ac"), test("c"), test("ac") true, SyntaxError, SyntaxError true, true, true true, true, true
new RegExp("a{4294967295}b") SyntaxError created, never matches created, never matches
/c|a{4294967295}b/.exec("c") SyntaxError at creation ["c"] ["c"]
/(?:z)?x{4294967295}/.test("") SyntaxError at the match false false
/(?<!a{4294967295})b/.test("b") SyntaxError at the match true true
new RegExp(sameText) after such a match SyntaxError created created
/(?:){4294967295}c|a{4294967295}b/.exec("c") SyntaxError at creation null, the search is abandoned ["c"]
/a{18446744073709551615}b|k/.exec("k") SyntaxError (number too large in {} quantifier) the same ["k"]

In Bun the same error shows in three more places: structuredClone(re) throws TypeError: Unable to deserialize data. after such a match, new URLPattern with such a group throws a TypeError, and bun test -t 'first|a{4294967295}b' exits with "expects a valid regular expression". All three come from the RegExp's error.

Of V8's test/mjsunit/regress/regress-126412.js (six patterns with such counts), four throw on main. With this PR all six give node's result.

Why a path that overflows cannot match

  • In setupAlternativeOffsets the position that overflows is the number of code units between the start of the enclosing alternative and a term. In emitDisjunction the sum that overflows is the input that was checked to be there plus the minimum of the alternative, or the distance a lookbehind reaches back.
  • Each is a count of code units that the subject has to have. More than UINT_MAX cannot be there.
  • test262 built-ins/RegExp/quantifier-integer-limit.js has b{9007199254740991}. It passed before, because a lone term does not overflow. b{9007199254740991}c did not.

The commits

  1. YarrInterpreter.cpp. emitDisjunction emits HaveCheckedInput(UINT_MAX) then CheckInput(UINT_MAX) and no terms for an alternative whose sum overflows, and for a positive lookbehind that reaches back too far. The first check holds only with UINT_MAX code units behind the position and the second only with UINT_MAX ahead, so the pair fails on every input. A negative lookbehind of that kind always holds, so nothing is emitted. The other 13 OffsetTooLarge exits are subtractions of a term position from the checked count and one re-add. They cannot overflow, stay as they are, and ByteCompiler::compile now asserts that none fires.
    Alone, this commit ends the two answers of one RegExp and every late error of a pattern that is built at creation. It leaves the pattern build's refusal: at creation, and at the first match for a pattern over 64 characters ("x".repeat(80) + "y{4294967295}").
  2. YarrPattern.cpp. setupDisjunctionOffsets takes OffsetTooLarge from setupAlternativeOffsets as "this alternative". It clears the terms, which have no usable offsets, and sets the minimum size to UINT_MAX. PatternAlternative::cannotMatch() names that state and emitDisjunction emits the failing pair for it. An alternative that has to match a group of such alternatives adds UINT_MAX to its position and overflows in turn. That sum (a group with a fixed count of one) had no overflow check. It needed none while an overflow inside the group was an error.
    A minimum size over INT_MAX sets m_containsUnsignedLengthPattern, so the pattern runs in the interpreter and never reaches the JIT. That gate is older than this PR. Two debug assertions at the JIT entry points state it.
  3. The test only. Each pattern of its table also runs in a RegExp that has not run before and whose first call is test(). The d flag gives that RegExp: the same text with the same flags comes from RegExpCache, which returns the RegExp that already ran.
  4. regexp-nested-quantifier-checked-offset.js, the test of [JSC] Fix Yarr JIT abort when nested alternatives claim more than INT_MAX characters #862, also runs with --useRegExpJIT=0 and with --useLazyRegExpPatternConstruction=0.

Runs (jsc of 5ce9596 and of its base 274ebb3, same flags: release, assertions on. node v26.3.0 is the reference. The generator and the three-way driver are not in the tree. The branch moved since onto 7961839: the upstream sync #860, #862, #807 and #881. The RegExp changes in them are the JIT fix of #862 and upstream's fast path for \r?\n. The diff in Source/ is the same. With the CI build of this head, c9cdf23, the new test, the test of #862 and 7 related stress tests pass in the three modes.)

check base this PR
20,000 generated patterns with counts near 2^31 and 2^32, 13 subjects each: refused at creation / throw at first match 2,972 / 4,142 0 / 0
of those, patterns for which node matches a subject 1,230 / 1,748
the same 20,000 with the first commit only 2,972 / 3,506, and 6,478 / 0 with --useLazyRegExpPatternConstruction=0
600,000 such patterns (default, --useRegExpJIT=0, --useLazyRegExpPatternConstruction=0, 200,000 each): this error 0
300,000 patterns with alternations of 8 to 19 alternatives (the fork's prefix merge and dispatch fold), the same three modes: this error 3,651 / 7,978 in 20,000 0
100,000 patterns with small counts only: a result that differs from the base 0
all of the above: a pattern the base accepted gives a different result / crashes, assertion failures 0 / 0
JSTests/stress files with regexp, regex or yarr in the name, every mode, --memory-limited as in CI (5,603 runs) 5,603 pass
LayoutTests/js and fast/regex, regexp tests (364 runs) 364 pass
test262 built-ins/RegExp, language/literals/regexp, the String methods that take a RegExp, sloppy and strict (5,066 runs) 5,066 pass 5,066 pass
debug + ASan jsc: the new test and 7 related stress tests in 3 modes, and 50,000 generated patterns 0 assertion failures, 0 ASan reports
  • Patterns that differ from node after the change: 7 in 1,100,000. The base accepts all 7 and gives this PR's result. Five come from one V8 bug, a /u class that matches a code point outside the BMP before $: /[\u{10235}]b$/u does not match "a\u{10235}b" in node. One comes from another: /(?:[^]+?x^|a?)+^/ does not match "a" in node. One is a search that Yarr abandons at its match limit after 9 seconds, where node finds the match in 1 second.
  • Not counted as a difference: a /u match that would start between the halves of a surrogate pair (A6 of BUN-TEST-DIFFERENCES.md).
  • The generator gives an atom that can match the empty string small counts only. With huge counts on such atoms too (2,500 patterns, run on a jsc that logs each search Yarr abandons): 122 patterns differ from node, 61 that the base refused and 61 that it accepts with the same result. For every subject that differs, node throws a RangeError or Yarr abandoned the search. For 11 of the 61 that the base refused, node matches a subject and this PR reports no match.
  • A minimum of 2^64 - 1 or more: 19,486 of 100,000 patterns that draw from such counts are refused at creation with number too large in {} quantifier, and node matches a subject for 8,276 of them. The same on the base.

Cost (instructions counted by single-stepping the function, for 982 regex literals from TypeScript, Prettier, React and Bun's built-in modules)

base first commit this PR
Yarr::byteCompile, per compile (983 compiles, JIT off) 3,448.8 3,447.6 3,453.4
YarrPattern build, per build (474 builds of 160 literals) 11,472.2 11,472.2 11,465.9
RegExp::match, RegExpCache, RegExp::finishCreation not touched not touched
ByteCompiler::emitDisjunction, bytes (jsc, -O3, no LTO) 2,328 2,597, and 28 for the out-of-line helper
setupDisjunctionOffsets, bytes 513 563
data members none added none added
/(?:z)?x{4294967295}/, 100 test("") calls: pattern builds / byte compiles / throws 3 / 1 refused / 100 3 / 1 / 0

Not in this PR

  • YarrParser.h refuses a quantifier minimum of 2^64 - 1 or more (QuantifierTooLarge). V8 accepts it. The parser cannot order two saturated counts, so that is its own change, and stress/regexp-max-quantifier.js and LayoutTests/fast/regex/overflow stay as upstream has them.
  • A group with a huge minimum count whose iterations match nothing makes Yarr abandon the search when its backtracking memory is full (about two million iterations) and report no match. V8 matches or throws a RangeError. That is main's behaviour for a pattern it accepts (/(?:){4294967295}b/.exec("b") is null). A pattern that was refused can now reach it. [JSC] A RegExp search that Yarr abandons throws a RangeError #343 turns that result into a RangeError.
  • The error that stays in the shared RegExp is gone for this error code only. A RegExp whose build or compile runs out of stack during a match still keeps regular expression too large (!isSafeToRecurse() at YarrPattern.cpp:1965, :2035 and :2666 on main), and a v class set over 64 characters can still be refused at its first match ([JSC] Lazy RegExp creation reports two YarrPattern build errors at creation again, and v MayContainStrings follows ECMA-262 #835's parser commit).
  • A pattern that was refused now runs. One with nested quantifiers can backtrack for a long time, as the same shape with small counts does.
  • Nothing is filed upstream or at test262 yet. WebKit/WebKit (0116e2a) refuses new RegExp("c|a{4294967295}b") at creation and /(?:z)?x{4294967295}/.test("") at the match as well. It does not have the two answers of one RegExp.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 485db9d1-8a8e-48b9-ab23-04d251b54ddd
📥 Commits

Reviewing files that changed from the base of the PR and between 7d0c8a7 and 5c37134.

📒 Files selected for processing: 14
  • CLAUDE.md
  • JSTests/BUN-TEST-DIFFERENCES.md
  • JSTests/stress/regexp-bytecode-compilation-fail.js
  • JSTests/stress/regexp-max-size.js
  • JSTests/stress/regexp-required-input-beyond-string-length.js
  • JSTests/stress/regexp-test-minimum-length-filter.js
  • JSTests/stress/regress-159954.js
  • LayoutTests/js/regexp-unicode-expected.txt
  • LayoutTests/js/script-tests/regexp-unicode.js
  • Source/JavaScriptCore/runtime/OptionsList.h
  • Source/JavaScriptCore/yarr/YarrInterpreter.cpp
  • Source/JavaScriptCore/yarr/YarrJIT.cpp
  • Source/JavaScriptCore/yarr/YarrPattern.cpp
  • Source/JavaScriptCore/yarr/YarrPattern.h

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Walkthrough

Yarr now compiles alternatives whose required input exceeds representable string lengths as non-matching paths instead of rejecting them for offset overflow. The PR adds regression coverage and updates existing test expectations and documentation.

Changes

RegExp Required-Input Limits

Layer / File(s) Summary
Represent oversized alternatives
Source/JavaScriptCore/yarr/YarrPattern.h, Source/JavaScriptCore/yarr/YarrPattern.cpp
Yarr detects overflow while calculating minimum input sizes. It marks affected alternatives as unable to match and adds PatternAlternative::cannotMatch().
Compile impossible paths
Source/JavaScriptCore/yarr/YarrInterpreter.cpp, Source/JavaScriptCore/yarr/YarrJIT.cpp, Source/JavaScriptCore/runtime/OptionsList.h
The interpreter emits impossible input checks for overflowed paths and lookbehinds. The JIT adds assertions against unsigned-length patterns. The option description now refers to errors during initial pattern construction.
Update tests and documentation
JSTests/stress/*regexp*, JSTests/stress/regress-159954.js, LayoutTests/js/regexp-unicode-expected.txt, LayoutTests/js/script-tests/regexp-unicode.js, JSTests/BUN-TEST-DIFFERENCES.md, CLAUDE.md
Tests now expect oversized patterns to compile and fail to match, with coverage across alternatives, execution modes, and string APIs. The documentation records the behavior and updates the changed-test count.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 5c371

No confirmed issue currently prevents merging after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main YARR change: failing only the impossible path when required input exceeds string limits.
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.
Description check Passed The description is detailed and explains the problem, fix, scope, behavior changes, testing, performance impact, and remaining limitations. It does not include the required bug title and Bugzilla URL,…
Full details: Description check

Explanation

The description is detailed and explains the problem, fix, scope, behavior changes, testing, performance impact, and remaining limitations. It does not include the required bug title and Bugzilla URL, the “Reviewed by NOBODY (OOPS!).” line, or a concise template-style list of changed paths and functions.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use path_filters to narrow the review scope.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@robobun

robobun commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: ready for review.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Preview build of c9cdf23: autobuild-preview-pr-864-c9cdf235

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I reviewed this PR and did not find any bugs, but a human look is still worthwhile: it changes RegExp semantics in the YARR pattern builder and byte compiler (SyntaxError becomes a never-matching path), diverges six upstream tests from WebKit, and the description itself leaves the design choice between this approach and #835 open.

What was reviewed:

  • The two new cannotMatchFromHere() paths in emitDisjunction and the cannotMatch() state set by setupDisjunctionOffsets: HaveCheckedInput(UINT_MAX) cannot pass (pos is at most String::MaxLength) and Input::checkInput guards wrap, so the pair fails on any input; the continues emit nothing before the pair and skip only the trailing uncheckInput, which was not needed.
  • Whether a cleared alternative can reach the JIT: it gets m_minimumSize = UINT_MAX, which sets m_containsUnsignedLengthPattern at any nesting level, so the JIT-side m_saveInitialStartValue slot and the new JIT asserts are not reached; a fixed-count group of cleared alternatives overflows the enclosing position via the new check, except at position 0 where the sum stays exactly UINT_MAX and the existing CheckInput/offset arithmetic still holds.
  • Negative lookbehind dropped on overflow: correct, since its body can never match and its captures are undefined on success anyway; the new test covers interpreter, JIT, and eager-construction modes.
Extended reasoning...

The change touches Source/JavaScriptCore/yarr (YarrPattern.cpp, YarrInterpreter.cpp, YarrJIT.cpp, YarrPattern.h), an OptionsList.h description string, six upstream regexp tests re-pinned to the new behavior, a 369-line new stress test, and the BUN-TEST-DIFFERENCES.md and CLAUDE.md count bookkeeping. It touches no auth, injection, or data-exposure surface; the risk is engine correctness in bytecode generation for overflowing input offsets. It is not approvable automatically because the paths are owned by a CODEOWNERS entry (/Source/JavaScriptCore, /JSTests, /LayoutTests/js), the PR is an intentional semantic divergence from upstream WebKit with an explicitly unsettled alternative design (#835), and the control-flow changes in emitDisjunction (early continues and a switch break) require judgement about the pre-existing offset invariants that the remaining OffsetTooLarge exits rely on.

robobun added a commit to oven-sh/bun that referenced this pull request Oct 21, 2026
…s, the pattern is valid

The jsc-stress fixture is JSTests/stress/regexp-required-input-beyond-string-length.js
of oven-sh/WebKit#864 without its run directives. The URLPattern and
structuredClone cases are places where Bun passed the RegExp's
SyntaxError on.
robobun added a commit to oven-sh/bun that referenced this pull request Oct 21, 2026
autobuild-preview-pr-864-cfa7f07f: a RegExp path that needs more input
than a string can hold fails its match, and the pattern stays valid.
@robobun
robobun force-pushed the robobun/66f8c8b4/regexp-required-input-beyond-string-length branch from cfa7f07 to 5c37134 Compare October 21, 2026 13:28

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

robobun added a commit to oven-sh/bun that referenced this pull request Oct 21, 2026
…s, the pattern is valid

The jsc-stress fixture is JSTests/stress/regexp-required-input-beyond-string-length.js
of oven-sh/WebKit#864 without its run directives.

The URLPattern and structuredClone cases are places where Bun passed the
RegExp's SyntaxError on. The bun test -t, Bun.build plugin filter and
bun lint id-match cases are places where Bun compiles a pattern with Yarr
itself, with no RegExp object.
robobun added a commit to oven-sh/bun that referenced this pull request Oct 21, 2026
autobuild-preview-pr-864-fc3e289f: a RegExp path that needs more input
than a string can hold fails its match, and the pattern stays valid.
@robobun
robobun force-pushed the robobun/66f8c8b4/regexp-required-input-beyond-string-length branch from fc3e289 to dbd0713 Compare October 23, 2026 13:16

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

…ring can hold

ByteCompiler::emitDisjunction() sums, in checked 32-bit integers, the input
that has to be there for an alternative to match. When a sum passed UINT_MAX
it refused the whole pattern: RegExp::compile() stored OffsetTooLarge in the
RegExp, and every match threw "SyntaxError: Invalid regular expression:
pattern exceeds string length limits". new RegExp had accepted the pattern.

    const re = /(?:a|b*)+?c(?<!(?<=(?<=x{2147483647})y{2147483647})z{2147483647})/;
    re.test("ac");          // true, from JIT code
    re.test("c");           // SyntaxError: the JIT code gives this match to the interpreter
    re.test("ac");          // SyntaxError
    new RegExp(re.source);  // SyntaxError, while that RegExp is in RegExpCache

    /(?:z)?x{4294967295}/.test("")   // SyntaxError. V8: false
    /(?<!a{4294967295})b/.test("b")  // SyntaxError. V8: true

A sum that does not fit asks for more input than a string can hold
(String::MaxLength), so the alternative it belongs to can never match. The
other alternatives can. emitDisjunction() now emits two checks that no input
satisfies together in place of such an alternative, and in place of a
positive lookbehind that reaches back more than UINT_MAX. A negative
lookbehind of that kind always holds, so nothing is emitted for it.

The other OffsetTooLarge exits of emitDisjunction() guard the subtraction of
a term's position from the input checked for it, and one re-add of an amount
just subtracted. They cannot overflow and stay. ByteCompiler::compile()
asserts that none of them fires.

What this leaves: the pattern build (setupAlternativeOffsets) still refuses a
pattern whose offsets pass UINT_MAX. That is at creation, and at the first
match for a pattern over 64 characters, which is built there
(useLazyRegExpPatternConstruction): "x".repeat(80) + "y{4294967295}" is
created, throws at its first match, and the error stays in the RegExp.

* CLAUDE.md:
* JSTests/BUN-TEST-DIFFERENCES.md: A10.
* JSTests/stress/regexp-required-input-beyond-string-length.js: Added.
* JSTests/stress/regexp-bytecode-compilation-fail.js:
* JSTests/stress/regexp-test-minimum-length-filter.js:
* Source/JavaScriptCore/yarr/YarrInterpreter.cpp:
…han a string can hold

YarrPatternConstructor::setupAlternativeOffsets() gives each term its input
offset in a checked 32-bit integer. When an offset passed UINT_MAX it refused
the whole pattern with "SyntaxError: Invalid regular expression: pattern
exceeds string length limits": at new RegExp, or at the first match for a
pattern over 64 characters, which is built there.

    new RegExp("a{4294967295}b")                  // SyntaxError. V8: created
    new RegExp("c|a{4294967295}b").exec("c")      // SyntaxError. V8: ["c"]
    new RegExp("(?:a{4294967295}b)?c").exec("c")  // SyntaxError. V8: ["c"]

The offset is the input between the start of the enclosing alternative and
the term, so the alternative can never match, and the other alternatives
can. setupDisjunctionOffsets() now takes OffsetTooLarge from
setupAlternativeOffsets() as a statement about that alternative: it clears
the terms, which have no usable offsets, and sets the minimum size to
UINT_MAX. PatternAlternative::cannotMatch() names that state, and
ByteCompiler::emitDisjunction() emits its always-failing checks for it.

An alternative that has to match a group of such alternatives adds UINT_MAX
to its own position and overflows in turn. That sum (a group with a fixed
count of one) had no overflow check. It needed none while an overflow in the
group was an error.

A minimum size over INT_MAX sets m_containsUnsignedLengthPattern, so such a
pattern runs in the interpreter, as before. The Yarr JIT asserts that it
never gets one.

Not covered: YarrParser still refuses a quantifier minimum of 2^64 - 1 or
more ("number too large in {} quantifier").

* CLAUDE.md:
* JSTests/BUN-TEST-DIFFERENCES.md: A10.
* JSTests/stress/regexp-required-input-beyond-string-length.js:
* JSTests/stress/regexp-max-size.js:
* JSTests/stress/regress-159954.js:
* LayoutTests/js/regexp-unicode-expected.txt:
* LayoutTests/js/script-tests/regexp-unicode.js:
* Source/JavaScriptCore/runtime/OptionsList.h:
* Source/JavaScriptCore/yarr/YarrInterpreter.cpp:
* Source/JavaScriptCore/yarr/YarrJIT.cpp:
* Source/JavaScriptCore/yarr/YarrPattern.cpp:
* Source/JavaScriptCore/yarr/YarrPattern.h:
…first call is test()

The table ran exec() and then test() on each RegExp, and then created the
same text again. RegExpCache returns the same RegExp for the same text and
flags, so no pattern of the table was compiled for test() first. The table
now also creates each pattern with the d flag, which is another RegExp,
and calls test() on it before exec().

The comments now say what the second creation of the same text is for: an
error that a match left in the shared RegExp made that creation throw.

* JSTests/stress/regexp-required-input-beyond-string-length.js:
…T too

The test ran with the JIT only: the byte compiler refused six of its
thirteen patterns with "pattern exceeds string length limits". It does not
refuse them any more, so the test also runs with --useRegExpJIT=0 and with
--useLazyRegExpPatternConstruction=0.

* JSTests/stress/regexp-nested-quantifier-checked-offset.js:
@robobun
robobun force-pushed the robobun/66f8c8b4/regexp-required-input-beyond-string-length branch from dbd0713 to c9cdf23 Compare October 23, 2026 13:39
robobun added a commit to oven-sh/bun that referenced this pull request Oct 23, 2026
…s, the pattern is valid

The jsc-stress fixture is JSTests/stress/regexp-required-input-beyond-string-length.js
of oven-sh/WebKit#864 without its run directives.

The URLPattern and structuredClone cases are places where Bun passed the
RegExp's SyntaxError on. The bun test -t, Bun.build plugin filter and
bun lint id-match cases are places where Bun compiles a pattern with Yarr
itself, with no RegExp object.
robobun added a commit to oven-sh/bun that referenced this pull request Oct 23, 2026
autobuild-preview-pr-864-c9cdf235: a RegExp path that needs more input
than a string can hold fails its match, and the pattern stays valid.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants