Skip to content

fix: include the backslash in [[:punct:]] - #203

Merged
mrmlnc merged 2 commits into
micromatch:masterfrom
youdie006:fix/punct-backslash
Aug 27, 2026
Merged

fix: include the backslash in [[:punct:]]#203
mrmlnc merged 2 commits into
micromatch:masterfrom
youdie006:fix/punct-backslash

Conversation

@youdie006

Copy link
Copy Markdown
Contributor

The problem

[[:punct:]] does not match a backslash. The table at lib/constants.js:84 holds 31 characters where POSIX defines 32 — the backslash is absent.

Backslash is a legal character in a POSIX filename, and bash matches it:

pattern subject bash 5.2.21 picomatch
[[:punct:]] \ true false
a[[:punct:]]b a\b true false
*[[:punct:]]* x\y true false
[[:punct:]] ! true true
[[:punct:]] a false false

The last two rows are controls: the class works, only this one character is missing.

It is also inconsistent with picomatch's own tables

graph is \x21-\x7E and print is \x20-\x7E, so both already match the backslash:

graph  matches backslash: true
print  matches backslash: true
punct  matches backslash: false
alnum  matches backslash: false

POSIX defines graph as alnum plus punct. A character that is in graph but in neither of its two parts cannot be right, so this holds independently of what bash does.

Why it was not caught

The [[:punct:]] test at test/posix-classes.js:265 exercises ! ? # & @ + * : = | and never a backslash. Nothing asserted the buggy behaviour, so this is an untested gap rather than a deliberate deviation.

The change

One character added to the class in lib/constants.js. Two assertions embed the class source as an expected regex string (test/posix-classes.js:24 and :136) and are updated to match, as is the equivalent listed at README.md:585 and the test's own description.

assert(isMatch('\\', '[[:punct:]]')) is added to the existing punct test.

Verification

Suite: 1996 passing before, 1996 passing after.

Reverting only lib/constants.js and keeping the tests fails 3 — the two expected-regex assertions and the new backslash one — so the added assertion exercises this bug rather than the class in general.


Disclosure: this patch was prepared with AI assistance. The bash comparison, the table counts and the red/green check above were executed against this branch; happy to adjust anything on request.

youdie006 and others added 2 commits August 27, 2026 11:02
The punct table held 31 characters where POSIX defines 32; the backslash
was missing, so [[:punct:]] failed to match it. Backslash is a legal
character in a POSIX filename, and bash matches it:

  bash        [[:punct:]] vs \      -> true
  picomatch   [[:punct:]] vs \      -> false
  bash        a[[:punct:]]b vs a\b  -> true
  picomatch   a[[:punct:]]b vs a\b  -> false

picomatch also contradicted itself: graph (\x21-\x7E) and print
(\x20-\x7E) both match the backslash, and POSIX defines graph as
alnum + punct, so a character in graph but in neither of its parts
could not be right.

The existing punct test exercises ! ? # & @ + * : = | and never a
backslash, which is why this went unnoticed. Two assertions embed the
class source as an expected regex string and are updated to match, as is
the equivalent listed in the README.
The README is generated from .verb.md by verb, but the previous commit
only updated the README, so regenerating the docs would have dropped
the backslash from the documented [[:punct:]] equivalent again.

Also add the negation counterpart of the new assertion: since
[[:punct:]] now matches the backslash, [![:punct:]] must not.
@mrmlnc
mrmlnc merged commit 1fc1284 into micromatch:master Aug 27, 2026
22 checks passed
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