fix: escape regex metacharacters in WildcardMatch - #2916
Conversation
|
Did you read our contribution guide? https://taskfile.dev/docs/contributing#ai-usage-policy |
Fair point, sorry about that. Yeah I used an AI tool to clean up the writeup and I should've flagged the description – my bad. But the comments are mine. |
trulede
left a comment
There was a problem hiding this comment.
I would request that you probably should write a normal Task test to capture the behaviour from end-2-end. Similar table driven approach, which is good. Then drop the unit test from the PR if you are happy with that.
This code (AI generated, but I suspected as much) shows a faster algorithm which I think should be considered in the PR.
func (t *Task) WildcardMatch(name string) (bool, []string) {
names := append([]string{t.Task}, t.Aliases...)
for _, taskName := range names {
// First, quick check without regex if there are no wildcards
if !strings.Contains(taskName, "*") {
if taskName == name {
return true, nil
}
continue
}
pattern := regexp.QuoteMeta(taskName)
pattern = strings.ReplaceAll(pattern, `\*`, "(.*)")
regex := regexp.MustCompile("^" + pattern + "$")
wildcards := regex.FindStringSubmatch(name)
if len(wildcards) > 1 {
return true, wildcards[1:]
}
}
return false, nil
}
A task whose name contains a regex metacharacter breaks task matching for the whole Taskfile. WildcardMatch built a pattern from the raw task name, so a task named "c++" panicked in MustCompile and a task named "a.b" matched "axb". Escape the name with QuoteMeta before turning "*" back into the wildcard group, and skip the regex entirely when the name has no wildcard.
a16e7f6 to
f19bb31
Compare
What
A task whose name contains a regex metacharacter breaks task matching for the whole Taskfile — either with a hard panic or a silent mis-match.
(*Task).WildcardMatchbuilds a regex from the task name, translating only*, and callsregexp.MustCompileon it:The raw task name is injected into the pattern, so any other metacharacter is interpreted as regex syntax:
c++yields^c++$, andregexp.MustCompilepanics withinvalid nested repetition operator: ++.a.bmatches the callaxb(the.acts as a wildcard). A realistic footgun:deploy.prodgets run by a mistypedtask deploy-prod.FindMatchingTaskscallsWildcardMatch(call.Task)on every task whenever the requested name isn't a direct/alias match, so a single task with such a name breaks matching for the entire Taskfile.Fix
Escape the task name with
regexp.QuoteMetabefore building the pattern, then turn the (now escaped)\*back into the wildcard group:*remains the only wildcard; everything else is matched literally.Testing
Added
TestTaskWildcardMatchcovering the existingbuild-*wildcard behavior plus the metacharacter cases (c++,a.b,deploy.prod). On the current code the test panics (invalid nested repetition operator); with the fix it passes. The fulltaskfile/astpackage suite passes and the module builds clean.