@@ -27,6 +27,16 @@ func TestParsePMArgs(t *testing.T) {
2727 input : "test" ,
2828 expected : []string {"test" },
2929 },
30+ {
31+ name : "empty string" ,
32+ input : "" ,
33+ expected : nil ,
34+ },
35+ {
36+ name : "only spaces" ,
37+ input : " " ,
38+ expected : nil ,
39+ },
3040 {
3141 name : "snort hex inline: A|42|C|44|F" ,
3242 input : "A|42|C|44|F" ,
@@ -62,16 +72,31 @@ func TestParsePMArgs(t *testing.T) {
6272 input : "|41|" ,
6373 expected : []string {"a" },
6474 },
75+ {
76+ name : "multiple patterns with snort syntax" ,
77+ input : "A|42|C |44|F" ,
78+ expected : []string {"abc" , "df" },
79+ },
80+ {
81+ name : "snort syntax mixed with plain pattern" ,
82+ input : "plain |41 42| mixed" ,
83+ expected : []string {"plain" , "ab" , "mixed" },
84+ },
6585 {
6686 name : "unclosed pipe" ,
6787 input : "A|42" ,
6888 wantErr : true ,
6989 },
7090 {
71- name : "invalid hex value" ,
91+ name : "invalid hex value at end of pipe block " ,
7292 input : "|ZZ|" ,
7393 wantErr : true ,
7494 },
95+ {
96+ name : "invalid hex value before space inside pipe block" ,
97+ input : "|ZZ FF|" ,
98+ wantErr : true ,
99+ },
75100 }
76101
77102 for _ , tt := range tests {
@@ -131,6 +156,30 @@ func TestPMSnortSyntax(t *testing.T) {
131156 input : "abcdf" ,
132157 wantMatch : true ,
133158 },
159+ {
160+ name : "plain pattern still works" ,
161+ param : "foo bar" ,
162+ input : "here is bar" ,
163+ wantMatch : true ,
164+ },
165+ {
166+ name : "plain pattern no match" ,
167+ param : "foo bar" ,
168+ input : "nothing here" ,
169+ wantMatch : false ,
170+ },
171+ {
172+ name : "snort hex only pattern matches" ,
173+ param : "|41 42 43|" ,
174+ input : "xABCy" ,
175+ wantMatch : true ,
176+ },
177+ {
178+ name : "snort non-printable byte matches" ,
179+ param : "prefix|01|suffix" ,
180+ input : "prefix\x01 suffix" ,
181+ wantMatch : true ,
182+ },
134183 }
135184
136185 waf := corazawaf .NewWAF ()
@@ -148,3 +197,67 @@ func TestPMSnortSyntax(t *testing.T) {
148197 })
149198 }
150199}
200+
201+ func TestNewPMInvalidArgs (t * testing.T ) {
202+ invalidCases := []struct {
203+ name string
204+ param string
205+ }{
206+ {name : "unclosed pipe" , param : "A|42" },
207+ {name : "invalid hex" , param : "|ZZ|" },
208+ {name : "invalid hex before space in pipe" , param : "|ZZ FF|" },
209+ }
210+
211+ for _ , tt := range invalidCases {
212+ t .Run (tt .name , func (t * testing.T ) {
213+ _ , err := newPM (plugintypes.OperatorOptions {Arguments : tt .param })
214+ if err == nil {
215+ t .Errorf ("newPM(%q) expected error but got nil" , tt .param )
216+ }
217+ })
218+ }
219+ }
220+
221+ func TestPMEvaluateWithCapture (t * testing.T ) {
222+ waf := corazawaf .NewWAF ()
223+
224+ t .Run ("capture mode returns matches" , func (t * testing.T ) {
225+ op , err := newPM (plugintypes.OperatorOptions {Arguments : "foo bar baz" })
226+ if err != nil {
227+ t .Fatalf ("newPM: unexpected error: %v" , err )
228+ }
229+ tx := waf .NewTransaction ()
230+ tx .Capture = true
231+ if ! op .Evaluate (tx , "foo and bar" ) {
232+ t .Error ("expected match but got none" )
233+ }
234+ })
235+
236+ t .Run ("capture mode no match returns false" , func (t * testing.T ) {
237+ op , err := newPM (plugintypes.OperatorOptions {Arguments : "foo bar" })
238+ if err != nil {
239+ t .Fatalf ("newPM: unexpected error: %v" , err )
240+ }
241+ tx := waf .NewTransaction ()
242+ tx .Capture = true
243+ if op .Evaluate (tx , "nothing to see here" ) {
244+ t .Error ("expected no match but got one" )
245+ }
246+ })
247+
248+ t .Run ("capture mode stops after 10 matches" , func (t * testing.T ) {
249+ // Build a pattern that can match many times in one string.
250+ // "a" will match every 'a' in the input.
251+ op , err := newPM (plugintypes.OperatorOptions {Arguments : "a" })
252+ if err != nil {
253+ t .Fatalf ("newPM: unexpected error: %v" , err )
254+ }
255+ tx := waf .NewTransaction ()
256+ tx .Capture = true
257+ // 15 'a' chars separated by '-' to ensure 15 distinct matches.
258+ input := "a-a-a-a-a-a-a-a-a-a-a-a-a-a-a"
259+ if ! op .Evaluate (tx , input ) {
260+ t .Error ("expected match but got none" )
261+ }
262+ })
263+ }
0 commit comments