11package zabbix
22
33import (
4- "reflect"
54 "testing"
5+ "time"
66
7- "github.com/dlclark/regexp2"
87 "github.com/stretchr/testify/assert"
98)
109
@@ -63,70 +62,42 @@ func TestParseFilter(t *testing.T) {
6362 tests := []struct {
6463 name string
6564 filter string
66- want * regexp2. Regexp
65+ wantPattern string
6766 expectNoError bool
6867 expectedError string
6968 }{
7069 {
7170 name : "Simple regexp" ,
7271 filter : "/.*/" ,
73- want : regexp2 . MustCompile ( ".*" , regexp2 . RE2 ) ,
72+ wantPattern : ".*" ,
7473 expectNoError : true ,
7574 expectedError : "" ,
7675 },
7776 {
7877 name : "Not a regex" ,
7978 filter : "/var/lib/mysql: Total space" ,
80- want : nil ,
79+ wantPattern : "" ,
8180 expectNoError : true ,
8281 expectedError : "" ,
8382 },
8483 {
8584 name : "Regexp with modifier" ,
8685 filter : "/.*/i" ,
87- want : regexp2 . MustCompile ( "(?i).*" , regexp2 . RE2 ) ,
86+ wantPattern : "(?i).*" ,
8887 expectNoError : true ,
8988 expectedError : "" ,
9089 },
9190 {
9291 name : "Regexp with unsupported modifier" ,
9392 filter : "/.*/1" ,
94- want : nil ,
93+ wantPattern : "" ,
9594 expectNoError : false ,
9695 expectedError : "" ,
9796 },
98- {
99- name : "Pathological regex - nested quantifiers (a+)+" ,
100- filter : "/^(a+)+$/" ,
101- want : nil ,
102- expectNoError : false ,
103- expectedError : "error parsing regexp: potentially dangerous regex pattern detected" ,
104- },
105- {
106- name : "Pathological regex - (.*)* pattern" ,
107- filter : "/(.*)*/" ,
108- want : nil ,
109- expectNoError : false ,
110- expectedError : "error parsing regexp: potentially dangerous regex pattern detected" ,
111- },
112- {
113- name : "Pathological regex - overlapping alternation" ,
114- filter : "/(a|a)*/" ,
115- want : nil ,
116- expectNoError : false ,
117- expectedError : "error parsing regexp: potentially dangerous regex pattern detected" ,
118- },
119- {
120- name : "Pathological regex - consecutive quantifiers" ,
121- filter : "/a**/" ,
122- want : nil ,
123- expectNoError : false ,
124- expectedError : "error parsing regexp: potentially dangerous regex pattern detected" ,
125- },
12697 {
12798 name : "Safe complex regex" ,
12899 filter : "/^[a-zA-Z0-9_-]+\\ .[a-zA-Z]{2,}$/" ,
129- want : regexp2 . MustCompile ( "^[a-zA-Z0-9_-]+\\ .[a-zA-Z]{2,}$" , regexp2 . RE2 ) ,
100+ wantPattern : "^[a-zA-Z0-9_-]+\\ .[a-zA-Z]{2,}$" ,
130101 expectNoError : true ,
131102 expectedError : "" ,
132103 },
@@ -142,75 +113,42 @@ func TestParseFilter(t *testing.T) {
142113 assert .Error (t , err )
143114 assert .EqualError (t , err , tt .expectedError )
144115 }
145- if ! reflect .DeepEqual (got , tt .want ) {
146- t .Errorf ("parseFilter() = %v, want %v" , got , tt .want )
116+ if tt .wantPattern == "" {
117+ assert .Nil (t , got )
118+ } else {
119+ assert .NotNil (t , got )
120+ assert .Equal (t , tt .wantPattern , got .String ())
121+ // Verify that timeout is set for DoS protection
122+ assert .Equal (t , 5 * time .Second , got .MatchTimeout )
147123 }
148124 })
149125 }
150126}
151127
152- func TestIsPathologicalRegex (t * testing.T ) {
153- tests := []struct {
154- name string
155- pattern string
156- expected bool
157- }{
158- {
159- name : "Safe pattern" ,
160- pattern : "^[a-zA-Z0-9]+$" ,
161- expected : false ,
162- },
163- {
164- name : "Nested quantifiers (a+)+" ,
165- pattern : "^(a+)+$" ,
166- expected : true ,
167- },
168- {
169- name : "Nested quantifiers (a*)*" ,
170- pattern : "(a*)*" ,
171- expected : true ,
172- },
173- {
174- name : "Overlapping alternation (a|a)*" ,
175- pattern : "(a|a)*" ,
176- expected : true ,
177- },
178- {
179- name : "Consecutive quantifiers **" ,
180- pattern : "a**" ,
181- expected : true ,
182- },
183- {
184- name : "Consecutive quantifiers ++" ,
185- pattern : "a++" ,
186- expected : true ,
187- },
188- {
189- name : "Catastrophic (.*)* pattern" ,
190- pattern : "(.*)*" ,
191- expected : true ,
192- },
193- {
194- name : "Catastrophic (.+)+ pattern" ,
195- pattern : "(.+)+" ,
196- expected : true ,
197- },
198- {
199- name : "Safe alternation with different patterns" ,
200- pattern : "(cat|dog)*" ,
201- expected : false ,
202- },
203- {
204- name : "Safe quantifier usage" ,
205- pattern : "[0-9]+\\ .[0-9]*" ,
206- expected : false ,
207- },
208- }
209-
210- for _ , tt := range tests {
211- t .Run (tt .name , func (t * testing.T ) {
212- result := isPathologicalRegex (tt .pattern )
213- assert .Equal (t , tt .expected , result , "Pattern: %s" , tt .pattern )
214- })
128+ func TestParseFilterTimeout (t * testing.T ) {
129+ // Test with a pathological regex pattern that should trigger MatchTimeout
130+ filter := "/((((.*)*)*)*)*z/"
131+ compiled , err := parseFilter (filter )
132+
133+ // The regex should compile successfully with timeout protection
134+ assert .NoError (t , err )
135+ assert .NotNil (t , compiled )
136+ assert .Equal (t , 5 * time .Second , compiled .MatchTimeout )
137+
138+ // Test that the regex times out when matching against a problematic string
139+ // This string is crafted to trigger catastrophic backtracking
140+ testString := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 52 'a's, no 'z'
141+
142+ // The match should timeout and return an error
143+ match , err := compiled .MatchString (testString )
144+
145+ // We expect either a timeout error or the match to complete quickly if RE2 optimizations prevent catastrophic backtracking
146+ // In either case, the system should remain responsive
147+ assert .False (t , match ) // Should not match since there's no 'z'
148+
149+ // If there's an error, it should be related to timeout
150+ if err != nil {
151+ assert .Contains (t , err .Error (), "timeout" )
215152 }
216153}
154+
0 commit comments