Files
grafana-zabbix/pkg/zabbix/utils_test.go
Zoltán Bedi 5db35450a2 Fix: Remove regex pattern length restriction (#2087)
In this PR I removed the regex pattern length restriction because from
multi value variables this length can be easly reached, also if the
regex is going to be too long it will be caught in the timeout.

Fixes #2086
2025-09-23 11:51:31 +02:00

217 lines
5.0 KiB
Go

package zabbix
import (
"reflect"
"testing"
"github.com/dlclark/regexp2"
"github.com/stretchr/testify/assert"
)
func TestExpandItemName(t *testing.T) {
tests := []struct {
name string
itemName string
key string
expected string
}{
{
name: "UNQUOTED_PARAMS",
itemName: "CPU $2 time",
key: "system.cpu.util[,user,avg1]",
expected: "CPU user time",
},
{
name: "QUOTED_PARAMS_WITH_COMMAS",
itemName: "CPU $1 $2 $3",
key: "system.cpu.util[\"type=user,value=avg\",time,\"user\"]",
expected: "CPU type=user,value=avg time user",
},
{
name: "MULTIPLE_ARRAY_PARAMS",
itemName: "CPU $2 - $3 time",
key: "system.cpu.util[,[user,system],avg1]",
expected: "CPU user,system - avg1 time",
},
{
name: "MULTIPLE_ARRAY_PARAMS",
itemName: "CPU - $2 - $3 - $4",
key: "system.cpu.util[,[],[\"user,system\",iowait],avg1]",
expected: "CPU - - \"user,system\",iowait - avg1",
},
{
name: "UNICODE_PARAMS",
itemName: "CPU $1 $2 $3",
key: "system.cpu.util[\"type=\b5Ὂg̀9! ℃ᾭG,value=avg\",time,\"user\"]",
expected: "CPU type=\b5Ὂg̀9! ℃ᾭG,value=avg time user",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
item := &Item{
Name: tt.itemName,
Key: tt.key,
}
expandedName := item.ExpandItemName()
assert.Equal(t, tt.expected, expandedName)
})
}
}
func TestParseFilter(t *testing.T) {
tests := []struct {
name string
filter string
want *regexp2.Regexp
expectNoError bool
expectedError string
}{
{
name: "Simple regexp",
filter: "/.*/",
want: regexp2.MustCompile(".*", regexp2.RE2),
expectNoError: true,
expectedError: "",
},
{
name: "Not a regex",
filter: "/var/lib/mysql: Total space",
want: nil,
expectNoError: true,
expectedError: "",
},
{
name: "Regexp with modifier",
filter: "/.*/i",
want: regexp2.MustCompile("(?i).*", regexp2.RE2),
expectNoError: true,
expectedError: "",
},
{
name: "Regexp with unsupported modifier",
filter: "/.*/1",
want: nil,
expectNoError: false,
expectedError: "",
},
{
name: "Pathological regex - nested quantifiers (a+)+",
filter: "/^(a+)+$/",
want: nil,
expectNoError: false,
expectedError: "error parsing regexp: potentially dangerous regex pattern detected",
},
{
name: "Pathological regex - (.*)* pattern",
filter: "/(.*)*/",
want: nil,
expectNoError: false,
expectedError: "error parsing regexp: potentially dangerous regex pattern detected",
},
{
name: "Pathological regex - overlapping alternation",
filter: "/(a|a)*/",
want: nil,
expectNoError: false,
expectedError: "error parsing regexp: potentially dangerous regex pattern detected",
},
{
name: "Pathological regex - consecutive quantifiers",
filter: "/a**/",
want: nil,
expectNoError: false,
expectedError: "error parsing regexp: potentially dangerous regex pattern detected",
},
{
name: "Safe complex regex",
filter: "/^[a-zA-Z0-9_-]+\\.[a-zA-Z]{2,}$/",
want: regexp2.MustCompile("^[a-zA-Z0-9_-]+\\.[a-zA-Z]{2,}$", regexp2.RE2),
expectNoError: true,
expectedError: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseFilter(tt.filter)
if tt.expectNoError {
assert.NoError(t, err)
}
if tt.expectedError != "" {
assert.Error(t, err)
assert.EqualError(t, err, tt.expectedError)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseFilter() = %v, want %v", got, tt.want)
}
})
}
}
func TestIsPathologicalRegex(t *testing.T) {
tests := []struct {
name string
pattern string
expected bool
}{
{
name: "Safe pattern",
pattern: "^[a-zA-Z0-9]+$",
expected: false,
},
{
name: "Nested quantifiers (a+)+",
pattern: "^(a+)+$",
expected: true,
},
{
name: "Nested quantifiers (a*)*",
pattern: "(a*)*",
expected: true,
},
{
name: "Overlapping alternation (a|a)*",
pattern: "(a|a)*",
expected: true,
},
{
name: "Consecutive quantifiers **",
pattern: "a**",
expected: true,
},
{
name: "Consecutive quantifiers ++",
pattern: "a++",
expected: true,
},
{
name: "Catastrophic (.*)* pattern",
pattern: "(.*)*",
expected: true,
},
{
name: "Catastrophic (.+)+ pattern",
pattern: "(.+)+",
expected: true,
},
{
name: "Safe alternation with different patterns",
pattern: "(cat|dog)*",
expected: false,
},
{
name: "Safe quantifier usage",
pattern: "[0-9]+\\.[0-9]*",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isPathologicalRegex(tt.pattern)
assert.Equal(t, tt.expected, result, "Pattern: %s", tt.pattern)
})
}
}