Files

58 lines
1.6 KiB
Go
Raw Permalink Normal View History

package aviation
import (
"context"
"regexp"
"time"
)
const (
// DefaultRegexTimeout is the maximum time allowed for regex matching operations.
// This prevents ReDoS (Regular Expression Denial of Service) attacks from
// maliciously crafted inputs that cause catastrophic backtracking.
DefaultRegexTimeout = 100 * time.Millisecond
)
// MatchWithTimeout executes a regex match with timeout protection.
// It runs the regex matching in a goroutine and returns an error if the
// operation exceeds the specified timeout duration.
//
// This is critical for preventing ReDoS attacks where complex patterns
// (especially the FPL pattern with nested quantifiers) could hang indefinitely
// on malicious input.
//
// Parameters:
// - re: The compiled regular expression to match
// - input: The input string to match against
// - timeout: Maximum duration allowed for the match operation
//
// Returns:
// - []string: The match result (same format as regexp.FindStringSubmatch)
// - error: ValidationError if timeout occurs, nil otherwise
func MatchWithTimeout(re *regexp.Regexp, input string, timeout time.Duration) ([]string, error) {
type result struct {
match []string
}
resultChan := make(chan result, 1)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// Run regex matching in a goroutine
go func() {
match := re.FindStringSubmatch(input)
resultChan <- result{match: match}
}()
// Wait for either result or timeout
select {
case res := <-resultChan:
return res.match, nil
case <-ctx.Done():
return nil, &ValidationError{
Field: "regex_timeout",
Message: "regex matching exceeded timeout",
}
}
}