Skip to content

Fix extended star group directly after a star - #246

Merged
facelessuser merged 1 commit into
facelessuser:mainfrom
spicysharkco:fix/double-star-extglob
Oct 19, 2026
Merged

facelessuser merged 1 commit into
facelessuser:mainfrom
spicysharkco:fix/double-star-extglob

Conversation

@spicysharkco

Copy link
Copy Markdown
Contributor

fnmatch.fnmatch('abb', 'a**(b)', flags=fnmatch.EXTMATCH) returns False, and so does glob.globmatch('b', '**(a|b)b', flags=glob.GLOBSTAR | glob.EXTGLOB). Both should return True, as Bash does: **(b) is a * followed by the group *(b), which matches zero or more occurrences. The latest release, 11.1, returns False for both, and a**(b) matches only names ending in the literal (b).

The star that opens the group is consumed by the loop that collapses repeated stars, so (b) is matched as literal text. Before 11.0 that loop only ran at the start of a segment, so a**(b) worked up to 10.2.1. With GLOBSTAR, a ** at the start of a segment is read as a possible globstar, and with GLOBSTARLONG a third star is read as ***.

These three places now leave a star that is followed by ( when extended groups are enabled. A **(x) now compiles like a * followed by *(x), so **(a|aa)c can backtrack on a long name that does not match, as *+(a|aa)c already does.

I added three rows to TestFnMatch.cases and five to TestGlobMatch.cases. Without the fix, pytest tests/test_fnmatch.py tests/test_globmatch.py gives 8 failed, 866 passed, 64 skipped. With it, 874 passed, 64 skipped. The full suite passes with the fix. There is a changelog line under 11.2.

With the EXTMATCH or EXTGLOB flag, `fnmatch.fnmatch('abb', 'a**(b)')`
returned False. The second star opens the group `*(b)`, but the code that
collapses repeated stars consumed it, so `(b)` was matched as literal
text. At the start of a path segment with GLOBSTAR, `**(b)` had the same
problem because the two stars were read as a possible globstar, and with
GLOBSTARLONG so did `***(b)`, read as a possible `***`.

Stop collapsing at a star that is followed by `(` when extended groups
are enabled, and do not read such a star as the second star of `**` or
the third star of `***`.
@gir-bot gir-bot added S: needs-review Needs to be reviewed and/or approved. C: docs Related to documentation. C: fnmatch Fnmatch library. C: glob Glob library. C: pattern-parser Related to pattern parsing. C: source Related to source code. C: tests Related to testing. labels Oct 19, 2026
@facelessuser

Copy link
Copy Markdown
Owner

@gir-bot lgtm

@gir-bot gir-bot added S: approved The pull request is ready to be merged. and removed S: needs-review Needs to be reviewed and/or approved. labels Oct 19, 2026
@facelessuser

Copy link
Copy Markdown
Owner

Another good find.

@facelessuser
facelessuser merged commit 4e97d87 into facelessuser:main Oct 19, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C: docs Related to documentation. C: fnmatch Fnmatch library. C: glob Glob library. C: pattern-parser Related to pattern parsing. C: source Related to source code. C: tests Related to testing. S: approved The pull request is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants