From 9b67b7cb98ee053fee0fb4dd5e14c53926218477 Mon Sep 17 00:00:00 2001 From: Chris Moran Date: Wed, 31 Jan 2024 13:08:34 -0500 Subject: [PATCH] fix: update engine_regexp compile to use '{','}' as start, end delimiters if the regexp contains possessive match or lookbehind syntax. --- rule/engine_regexp.go | 16 ++++++++++++-- rule/engine_regexp_test.go | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/rule/engine_regexp.go b/rule/engine_regexp.go index 9635249c5f..65a68f240a 100644 --- a/rule/engine_regexp.go +++ b/rule/engine_regexp.go @@ -4,8 +4,10 @@ package rule import ( - "errors" "hash/crc64" + "strings" + + "github.com/pkg/errors" "github.com/dlclark/regexp2" @@ -23,7 +25,17 @@ func (re *regexpMatchingEngine) compile(pattern string) error { re.table = crc64.MakeTable(polynomial) } if checksum := crc64.Checksum([]byte(pattern), re.table); checksum != re.checksum { - compiled, err := compiler.CompileRegex(pattern, '<', '>') + startDelim := byte('<') + endDelim := byte('>') + if strings.Contains(pattern, "(?>") || strings.Contains(pattern, "(?<") { + if strings.ContainsRune(pattern, '{') && strings.ContainsRune(pattern, '}') { + startDelim = byte('{') + endDelim = byte('}') + } else { + return errors.Errorf("attempted to use regex 'possessive match' or regex 'lookbehind' without changing delimiters from '<...>' to '{...}' in: %s", pattern) + } + } + compiled, err := compiler.CompileRegex(pattern, startDelim, endDelim) if err != nil { return err } diff --git a/rule/engine_regexp_test.go b/rule/engine_regexp_test.go index 0b3e3985e9..ad65536fcf 100644 --- a/rule/engine_regexp_test.go +++ b/rule/engine_regexp_test.go @@ -29,6 +29,24 @@ func TestFindStringSubmatch(t *testing.T) { want: nil, wantErr: true, }, + { + name: "bad lookbehind (wrong delimiters)", + args: args{ + pattern: `urn:foo:<(?<=foo:)foobar>`, + matchAgainst: "urn:foo:foobar", + }, + want: nil, + wantErr: true, + }, + { + name: "bad possessive (wrong delimiters)", + args: args{ + pattern: `urn:foo:<(?>=foo:)foobar>`, + matchAgainst: "urn:foo:foobar", + }, + want: nil, + wantErr: true, + }, { name: "one group", args: args{ @@ -56,6 +74,33 @@ func TestFindStringSubmatch(t *testing.T) { want: []string{"bar"}, wantErr: false, }, + { + name: "positive lookbehind (?<=foo)bar", + args: args{ + pattern: `urn:foo:{(?<=foo:)foobar}`, + matchAgainst: "urn:foo:foobar", + }, + want: []string{"foobar"}, + wantErr: false, + }, + { + name: "negative lookbehind (?