FuzzSearchRegex tests the regex compilation and search functionality to ensure it handles malformed patterns gracefully and doesn't suffer from catastrophic backtracking
(f *testing.F)
| 11 | // to ensure it handles malformed patterns gracefully and doesn't suffer |
| 12 | // from catastrophic backtracking |
| 13 | func FuzzSearchRegex(f *testing.F) { |
| 14 | // Add seed corpus with various regex patterns |
| 15 | // Valid patterns |
| 16 | f.Add("test", "This is a test string") |
| 17 | f.Add("(?i)test", "This is a TEST string") |
| 18 | f.Add("foo|bar", "foo and bar") |
| 19 | f.Add("^start", "start of line\nnext line") |
| 20 | f.Add("end$", "at the end\nnext line") |
| 21 | f.Add("\\d+", "123 numbers 456") |
| 22 | f.Add("[a-z]+", "lowercase UPPERCASE") |
| 23 | |
| 24 | // Edge cases and potentially problematic patterns |
| 25 | f.Add("", "empty pattern") |
| 26 | f.Add(".", "any character") |
| 27 | f.Add(".*", "match everything") |
| 28 | f.Add(".+", "match something") |
| 29 | f.Add("\\", "backslash") |
| 30 | f.Add("(", "unclosed paren") |
| 31 | f.Add(")", "unmatched paren") |
| 32 | f.Add("[", "unclosed bracket") |
| 33 | f.Add("]", "unmatched bracket") |
| 34 | f.Add("[^]", "negated empty class") |
| 35 | f.Add("(?", "incomplete group") |
| 36 | |
| 37 | // Patterns that might cause performance issues |
| 38 | f.Add("(a+)+", "aaaaaaaaaaaaaaaaaaaaaaaab") |
| 39 | f.Add("(a*)*", "aaaaaaaaaaaaaaaaaaaaaaaab") |
| 40 | f.Add("(a|a)*", "aaaaaaaaaaaaaaaaaaaaaaaab") |
| 41 | f.Add("(.*)*", "any text here") |
| 42 | f.Add("(\\d+)+", "123456789012345678901234567890x") |
| 43 | |
| 44 | // Unicode patterns |
| 45 | f.Add("☺", "Unicode ☺ smiley") |
| 46 | f.Add("[一-龯]", "Chinese 中文 characters") |
| 47 | f.Add("\\p{L}+", "Unicode letters") |
| 48 | |
| 49 | // Very long patterns |
| 50 | f.Add(strings.Repeat("a", 1000), "long pattern") |
| 51 | f.Add(strings.Repeat("(a|b)", 100), "complex pattern") |
| 52 | |
| 53 | f.Fuzz(func(t *testing.T, pattern string, text string) { |
| 54 | // Test 1: Regex compilation should not panic |
| 55 | var reg *regexp.Regexp |
| 56 | var compileErr error |
| 57 | |
| 58 | func() { |
| 59 | defer func() { |
| 60 | if r := recover(); r != nil { |
| 61 | t.Errorf("regexp.Compile panicked with pattern %q: %v", pattern, r) |
| 62 | } |
| 63 | }() |
| 64 | |
| 65 | reg, compileErr = regexp.Compile(pattern) |
| 66 | }() |
| 67 | |
| 68 | // If compilation failed, that's OK - we're testing error handling |
| 69 | if compileErr != nil { |
| 70 | // This is expected for invalid patterns |