Skip to content

fix: preserve consecutive escaped backslashes - #226

Open
Kenoia wants to merge 1 commit into
micromatch:masterfrom
Kenoia:fix/preserve-escaped-backslash-runs
Open

Kenoia wants to merge 1 commit into
micromatch:masterfrom
Kenoia:fix/preserve-escaped-backslash-runs

Conversation

@Kenoia

@Kenoia Kenoia commented Oct 7, 2026

Copy link
Copy Markdown

A POSIX filename containing two consecutive backslashes is missed by its correctly escaped pattern, while the same pattern incorrectly matches a filename containing only one backslash.

const picomatch = require('picomatch');
const pattern = 'a' + '\\'.repeat(4) + 'b*';
const matches = picomatch(pattern, { windows: false });

matches('a' + '\\'.repeat(2) + 'b.txt'); // before: false; after: true
matches('a' + '\\'.repeat(1) + 'b.txt'); // before: true; after: false

The fast parser and tokenizer both collapse consecutive escapes. Patterns containing escaped backslash pairs now use the tokenizer, which preserves each pair as one literal backslash. Longer runs compile to a fixed repetition, so a 65K-character pattern still has a compact regex. An odd final escape continues to escape the following glob character. Explicit unescape: true behavior is retained.

The existing long-escape test is updated to expect 32,750 literal backslashes from 65,500 escape characters, and to reject the shorter filename. Its negation, invalid-regex and length-limit checks remain in place.

Related to mrmlnc/fast-glob#262, identified while investigating POSIX backslash filenames. This addresses the matcher behavior for consecutive literal backslashes; fast-glob's path conversion and task-base handling require separate work.

Validation on Arch Linux:

  • All 10 new regression tests fail against base 9fab7bf61913ea334c4203ed321c426cfde44a42 and pass with this change.
  • Node 26.10.0: npm run lint and npm run test:ci pass, 2,008 tests; line coverage 95.7%, branch coverage 91.89%.
  • Node 24.15.0: complete Mocha suite passes, 2,008 tests.
  • 126 comparisons against Bash agree on literal backslashes and escaped glob characters.
  • 224 comparisons of unescape: true across fast/full parsing and Windows/POSIX options produce the same regex sources as the base.
  • A focused 30-sample timing check measured median full parsing at about 0.067 ms for 32K escape characters and 0.132 ms for 64K. The regex body is 11 characters at the largest input; the 65,536-character input limit remains enforced.

Native Windows and macOS runs and the other supported Node versions await the existing CI matrix.

Keep escaped backslash pairs as exact repetitions instead of collapsing literal filenames. Route escape runs through the tokenizer while preserving unescape behavior and the pattern length limit.

Refs mrmlnc/fast-glob#262.
@Kenoia
Kenoia marked this pull request as ready for review October 7, 2026 12:55
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:55

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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