Skip to content

fix: prevent wildcard pattern from overriding exact match in FindBestPatternMatch#3618

Open
kuishou68 wants to merge 1 commit into
microsoft:mainfrom
kuishou68:fix/find-best-pattern-match-exact-override
Open

fix: prevent wildcard pattern from overriding exact match in FindBestPatternMatch#3618
kuishou68 wants to merge 1 commit into
microsoft:mainfrom
kuishou68:fix/find-best-pattern-match-exact-override

Conversation

@kuishou68
Copy link
Copy Markdown

Closes #3617

Problem

In internal/core/pattern.go, FindBestPatternMatch uses pattern.StarIndex as the betterness criterion when comparing matched patterns. For exact matches, StarIndex == -1, so after selecting an exact match, longestMatchPrefixLength is set to -1. Any subsequent wildcard pattern with StarIndex >= 0 satisfies pattern.StarIndex > longestMatchPrefixLength (N > -1), incorrectly overriding the exact match.

Example: given patterns ["foo/bar" (exact), "foo/*" (StarIndex=4)] and candidate "foo/bar":

  1. "foo/bar" matches → longestMatchPrefixLength = -1
  2. "foo/*" matches → 4 > -1 = true → overrides exact match ❌

Root Cause vs Original TypeScript

The original TypeScript uses pattern.prefix.length (the full text length for exact matches) as the betterness criterion — a large positive number that cannot be overridden by any wildcard. The Go port incorrectly used pattern.StarIndex (which is -1 for exact matches).

Fix

Set longestMatchPrefixLength = math.MaxInt when an exact match is found, so no wildcard can override it — matching the semantics of the original TypeScript.

if pattern.StarIndex == -1 {
    // Exact match: use math.MaxInt so no wildcard pattern can override it.
    longestMatchPrefixLength = math.MaxInt
} else {
    longestMatchPrefixLength = pattern.StarIndex
}

Signed-off-by: cocoon 54054995+kuishou68@users.noreply.github.com

…PatternMatch (Closes microsoft#3617)

The original TypeScript uses pattern.prefix.length as the betterness criterion,
which for exact matches equals the full string length. The Go port used
pattern.StarIndex directly, which is -1 for exact matches, allowing any
subsequent wildcard (StarIndex >= 0) to incorrectly override the exact match.

Fix: set longestMatchPrefixLength = math.MaxInt when an exact match is found.

Signed-off-by: cocoon <54054995+kuishou68@users.noreply.github.com>
@jakebailey
Copy link
Copy Markdown
Member

This will require a test, preferably one we can cross check with the old code to double check it

@DanielRosenwasser
Copy link
Copy Markdown
Member

DanielRosenwasser commented Apr 27, 2026

As far as I remember, this code path isn't supposed to be hit for an exact match. Did you actually run into a problem with a specific project?

@kuishou68
Copy link
Copy Markdown
Author

Yes — ran into it while tracing how tsconfig.json path pattern resolution works in the Go port. With the pattern list ["src/foo/bar", "src/foo/*"] and candidate "src/foo/bar", the exact match gets selected first (StarIndex=-1), but the wildcard (StarIndex=7) satisfies 7 > -1 and overwrites it. The original TypeScript code uses prefixLength which stays 0 for exact matches, so the wildcard's positive prefix length can't beat it.

I can add a test that runs both the Go and a reference table side-by-side if that would help verify the fix.

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.

fix: FindBestPatternMatch incorrectly allows wildcard pattern to override exact match

3 participants