Repository navigation
fix: treat a brace range with no bounds as literal text - #232
Open
Kumar44developer wants to merge 1 commit into
Open
Kumar44developer wants to merge 1 commit into
Kumar44developer wants to merge 1 commit into
Conversation
A range with no bounds, such as '{..}', was expanded to the empty character class '[]'. An empty class can never match, so the whole pattern became unmatchable: isMatch('a{..}', '*{..}') returned false and no string could match '*{..}'.
Collect the range bounds before consuming the tokens so a boundless range can fall through to the existing literal-brace handling, which is what bash and the nobrace option already do. The second dot of a dots token is now escaped as well, so the token still matches literal dots when it is rendered as literal text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Treat a brace range with no bounds as literal text
Problem
A brace range with no bounds, such as
{..}, is expanded to the empty character class[]:[]is a valid JavaScript character class, sonew RegExpdoesn't throw and the existing fallback inexpandRangenever kicks in — but an empty class can never match anything. That makes the entire pattern unmatchable:There is no string that
*{..}can match.This is easy to miss because
isMatch(p, p)short-circuits on exact string equality, soisMatch('{..}', '{..}')returnstruewhile the compiled regex matches nothing.makeReexposes the real behaviour.Both bash and picomatch's own
nobraceoption treat{..}as literal text:Fix
The range bounds are now collected before the tokens are consumed, so that a boundless range can fall through to the existing literal-brace handling instead of being expanded:
Ranges that do have bounds are untouched — the same tokens are popped and
expandRangeis called with the same arguments, so{a..c}still compiles to[a-c]and{1..3}to[1-3].This also escapes the second dot of a
dotstoken. Previously the token's output was\.., with the second dot left raw. That never mattered while the output was always replaced byexpandRange, but now that the token can be rendered as literal text the unescaped dot would act as a wildcard and{..}would match{.X}.Scope
This fixes only the boundless case, where the result can never match under any interpretation. Ranges with a single bound (
{a..},{...}) still expand to a one-character class; those have a plausible-but-debatable intended behaviour, so I left them alone rather than fold a semantics change into a bug fix. Happy to follow up if you'd like them treated as literal too.Tests
Added a test to
test/braces.jscovering the literal matches, the patterns where the equality short-circuit can't hide the bug, and the escaped dots. Verified it fails on currentmaster:With the fix the full suite passes — 1999 passing (1998 before, plus the new test) — and
eslintis clean.