Skip to content

[Finder] Fix Glob::toRegex() producing an invalid regex for bracket expressions containing a slash - #67785

Merged
nicolas-grekas merged 1 commit into
symfony:6.4from
0xABCD01:fix/glob-bracket-slash
Nov 2, 2026
Merged

nicolas-grekas merged 1 commit into
symfony:6.4from
0xABCD01:fix/glob-bracket-slash

Conversation

@0xABCD01

@0xABCD01 0xABCD01 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor
Q A
Branch? 6.4
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #67784
License MIT

Glob::bracketExpressionToRegex() returns null when a / comes before the closing ], by design: the [ is then meant to be a literal character, like an unclosed [. The caller did not honor that. On null the [ fell through to the plain-character branch and was copied into the regex unescaped; the following / marked a new segment start, so a (?=[^.]) lookahead was injected into the middle of the class:

Glob::toRegex('a[/]b');
// '#^(?=[^\.])a[/(?=[^\.])]b$#' — preg_match() fails on this regex

As a result, every glob whose bracket expression contains a slash ([/], [a/b], x[y/z]w, ...) made preg_match() fail with a compilation warning and matched nothing, including through Finder::name().

This PR appends \[' when the bracket scan returns null, mirroring the unclosed-bracket case one branch over. The rest of the pattern keeps being processed as ordinary glob text: a valid bracket expression later in the pattern still parses, and a *after the invalidated[` stays a wildcard. A differential run over ~146k pattern/text pairs against the previous implementation shows behavior changes only for patterns with a slash inside a bracket expression.

@nicolas-grekas

Copy link
Copy Markdown
Member

Thanks for the fix. I pushed a small rework: bracketExpressionToRegex() now returns \[ itself when a / comes before the ]. The caller has no null to handle anymore. I also added a case for a [ nested in such a bracket ([a[/]).

Treating the [ as a literal is what POSIX asks for in pathname patterns: a[b/c]d only matches a[b/c]d. glob() on Linux, bash and Python do the same.

@nicolas-grekas

Copy link
Copy Markdown
Member

Thank you @0xABCD01.

@nicolas-grekas
nicolas-grekas merged commit caf9928 into symfony:6.4 Nov 2, 2026
15 checks passed
This was referenced Nov 4, 2026
nicolas-grekas added a commit that referenced this pull request Nov 6, 2026
…s wrong (KalimeroMK)

This PR was merged into the 6.4 branch.

Discussion
----------

[Finder] Fix three bracket expressions Glob::toRegex() gets wrong

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

#67785 stopped `Glob::toRegex()` returning an invalid regex for a bracket expression holding a `/`.
Three shapes still get it wrong. I compared every result below against PHP's own `glob()` on a
directory holding the matching names.

**`[:alpha:]` compiles to nothing.** PCRE reads the whole class as a POSIX one and refuses it:

```php
preg_match(Glob::toRegex('[:alpha:]'), 'a');
// Warning: preg_match(): Compilation failed
// bool(false)
```

A POSIX class needs the outer brackets, so `[:alpha:]` is the set of the characters `:alpha`, and
`glob('[:alpha:]')` matches `:` and `a`. The `:` is escaped now, and `[[:alpha:]]` is untouched.

**`[[-?]` compiles to nothing.** Its range runs backwards, which POSIX leaves undefined and PCRE
rejects. `glob('[[-?]')` matches nothing, not even a file of that name, so the bracket expression
becomes `(?!)` when PCRE will not take it.

**`[[:alpha:]` matched the wrong thing.** `$scanEnd` records that no `]` closed the `[`, and the
next `[` before that point reuses the answer. That is wrong for a `[` the scan swallowed as part of
a `[:...:]`, which can still open a bracket expression of its own: `glob('[[:alpha:]')` matches
`[:` and `[a`, not the literal pattern, and `glob('[[:alpha:]/]')` matches `[a/]`. The assertion in
`testGlobToRegexBracketsAfterAnUnclosedOne` changes for that reason.

Comparing `Glob::toRegex()` with `fnmatch()` over 12906 pattern/subject pairs leaves no pattern
that fails to compile.

Commits
-------

4b6d3b0 [Finder] Fix three bracket expressions Glob::toRegex() gets wrong
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants