From c21c47d54c9748679370d23280b53e88f5111060 Mon Sep 17 00:00:00 2001 From: Roshan Piyush Date: Thu, 23 Jan 2025 16:50:41 +0530 Subject: [PATCH] Test hash uniqueness --- internal/corazawaf/rule_test.go | 138 ++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 17 deletions(-) diff --git a/internal/corazawaf/rule_test.go b/internal/corazawaf/rule_test.go index 5a3916de0..daa7f040c 100644 --- a/internal/corazawaf/rule_test.go +++ b/internal/corazawaf/rule_test.go @@ -5,7 +5,9 @@ package corazawaf import ( "errors" + "hash/fnv" "strconv" + "strings" "testing" "github.com/corazawaf/coraza/v3/debuglog" @@ -14,6 +16,7 @@ import ( "github.com/corazawaf/coraza/v3/internal/corazarules" "github.com/corazawaf/coraza/v3/types" "github.com/corazawaf/coraza/v3/types/variables" + "github.com/stretchr/testify/assert" ) func TestMatchEvaluate(t *testing.T) { @@ -384,23 +387,6 @@ func TestAddTransformation(t *testing.T) { } } -func BenchmarkAddTransformationUnique(b *testing.B) { - transformation := func(input string) (string, bool, error) { - return "Test", true, nil - } - b.ResetTimer() - b.RunParallel(func(p *testing.PB) { - rule := NewRule() - for p.Next() { - transformationName := "transformation" + b.Name() - err := rule.AddTransformation(transformationName, transformation) - if err != nil { - b.Fatalf("Failed to add a transformation: %s", err.Error()) - } - } - }) -} - func TestAddTransformationEmpty(t *testing.T) { rule := NewRule() transformationName := "" @@ -633,3 +619,121 @@ func TestExpandMacroAfterWholeRuleEvaluation(t *testing.T) { t.Errorf("Expected ArgsGet-data, got %s", matchdata[0].Data()) } } + +func BenchmarkAddTransformationSame(b *testing.B) { + transformation := func(input string) (string, bool, error) { + return "Test", true, nil + } + b.ResetTimer() + rule := NewRule() + for i := 0; i < b.N; i++ { + transformationName := "transformation" + err := rule.AddTransformation(transformationName, transformation) + if err != nil { + b.Fatalf("Failed to add a transformation: %s", err.Error()) + } + } +} + +func BenchmarkAddTransformationUnique(b *testing.B) { + transformation := func(input string) (string, bool, error) { + return "Test", true, nil + } + b.ResetTimer() + rule := NewRule() + for i := 0; i < b.N; i++ { + transformationName := "transformation" + b.Name() + err := rule.AddTransformation(transformationName, transformation) + if err != nil { + b.Fatalf("Failed to add a transformation: %s", err.Error()) + } + } +} + +func BenchmarkAddTransformationUniqueParallel(b *testing.B) { + transformation := func(input string) (string, bool, error) { + return "Test", true, nil + } + b.ResetTimer() + b.RunParallel(func(p *testing.PB) { + rule := NewRule() + for p.Next() { + transformationName := "transformation" + b.Name() + err := rule.AddTransformation(transformationName, transformation) + if err != nil { + b.Fatalf("Failed to add a transformation: %s", err.Error()) + } + } + }) +} + + +func BenchmarkAddTransformationSameParallel(b *testing.B) { + transformation := func(input string) (string, bool, error) { + return "Test", true, nil + } + b.ResetTimer() + b.RunParallel(func(p *testing.PB) { + for p.Next() { + rule := NewRule() + transformationName := "transformation" + err := rule.AddTransformation(transformationName, transformation) + if err != nil { + b.Fatalf("Failed to add a transformation: %s", err.Error()) + } + } + }) +} + +func TestGetTransformationID(t *testing.T) { + // create an array of transformations using following string + transformations_values := []string{ + "t:none,t:lowercase", + "t:none", + "t:none,t:htmlEntityDecode", + "t:none,t:lowercase", + "t:none,t:lowercase,t:removeWhiteSpace", + "t:none,t:urlDecode", + "t:none,t:urlDecode,t:urlDecodeUni", + "t:none,t:urlDecodeUni", + "t:none,t:urlDecodeUni,t:base64Decode", + "t:none,t:urlDecodeUni,t:cmdLine", + "t:none,t:urlDecodeUni,t:cmdLine,t:lowercase,t:removeWhiteSpace", + "t:none,t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase,t:removeWhiteSpace", + "t:none,t:urlDecodeUni,t:compressWhitespace", + "t:none,t:urlDecodeUni,t:htmlEntityDecode", + "t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase", + "t:none,t:urlDecodeUni,t:lowercase", + "t:none,t:urlDecodeUni,t:lowercase,t:urlDecode,t:htmlEntityDecode,t:jsDecode", + "t:none,t:urlDecodeUni,t:replaceComments", + "t:none,t:urlDecodeUni,t:urlDecode,t:htmlEntityDecode,t:jsDecode", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:compressWhitespace", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:lowercase,t:removeNulls", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:lowercase", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,t:removeWhiteSpace", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls", + "t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine", + } + hashes := make(map[uint64]string) + for _, value := range transformations_values { + // split the string by comma + transformations := strings.Split(value, ",") + currentID := 0 + // iterate over the transformations + for _, transformation := range transformations { + transformation = strings.Split(strings.Trim(transformation, " "), ":")[1] + nextName := strconv.Itoa(currentID) + "+" + transformation + hasher := fnv.New64a() + hasher.Write([]byte(nextName)) + id := hasher.Sum64() + oldname, ok := hashes[id] + if ok { + assert.Equal(t, oldname, nextName, "Hash collision detected for %s and %s:: %d", oldname, nextName, id) + } + hashes[id] = nextName + currentID = int(id) + assert.NotEqual(t, id, 0) + } + } +} \ No newline at end of file