Skip to content

Commit 842d22a

Browse files
Copilotfzipi
andcommitted
test: add full coverage tests for pm snort syntax implementation
Agent-Logs-Url: https://github.com/corazawaf/coraza/sessions/bf792533-4ef4-4be3-8c71-38d5647544f9 Co-authored-by: fzipi <3012076+fzipi@users.noreply.github.com>
1 parent e334aa1 commit 842d22a

1 file changed

Lines changed: 114 additions & 1 deletion

File tree

internal/operators/pm_test.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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\x01suffix",
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

Comments
 (0)