Skip to content

Commit 4bcf23c

Browse files
authored
Merge branch 'main' into use_request_body
2 parents b0f4323 + 70f1746 commit 4bcf23c

25 files changed

+515
-139
lines changed

Diff for: .github/workflows/codeql-analysis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ jobs:
1313
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
1414

1515
- name: Initialize CodeQL
16-
uses: github/codeql-action/init@396bb3e45325a47dd9ef434068033c6d5bb0d11a # v3
16+
uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3
1717
with:
1818
languages: go
1919

2020
- name: Autobuild
21-
uses: github/codeql-action/autobuild@396bb3e45325a47dd9ef434068033c6d5bb0d11a # v3
21+
uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3
2222

2323
- name: Perform CodeQL Analysis
24-
uses: github/codeql-action/analyze@396bb3e45325a47dd9ef434068033c6d5bb0d11a # v3
24+
uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3

Diff for: .github/workflows/regression.yml

+35-18
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,29 @@ on:
1111
paths-ignore:
1212
- "**/*.md"
1313
- "LICENSE"
14-
1514
jobs:
15+
# Generate matrix of tags for all permutations of the tests
16+
generate-matrix:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
tags: ${{ steps.generate.outputs.tags }}
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
23+
24+
- name: Generate tag combinations
25+
id: generate
26+
run: |
27+
go run mage.go tagsmatrix > tags.json
28+
echo "::set-output name=tags::$(cat tags.json)"
29+
shell: bash
1630
test:
31+
needs: generate-matrix
1732
strategy:
1833
matrix:
1934
go-version: [1.22.x, 1.23.x]
2035
os: [ubuntu-latest]
36+
build-flag: ${{ fromJson(needs.generate-matrix.outputs.tags) }}
2137
runs-on: ${{ matrix.os }}
2238
steps:
2339
- name: Checkout code
@@ -26,36 +42,37 @@ jobs:
2642
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5
2743
with:
2844
go-version: ${{ matrix.go-version }}
29-
cache: true
45+
cache: true
3046
- name: Tests and coverage
31-
run: go run mage.go coverage
47+
run: |
48+
export BUILD_TAGS=${{ matrix.build-flag }}
49+
go run mage.go coverage
3250
- name: "Codecov: General"
33-
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
51+
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5
3452
if: ${{ matrix.go-version == '1.22.x' }}
3553
with:
3654
files: build/coverage.txt
37-
flags: default
55+
flags: default,${{ matrix.build-flag }}
56+
token: ${{ secrets.CODECOV_TOKEN }}
3857
- name: "Codecov: Examples"
39-
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
58+
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5
4059
if: ${{ matrix.go-version == '1.22.x' }}
4160
with:
4261
files: build/coverage-examples.txt
43-
flags: examples
62+
flags: examples+${{ matrix.build-flag }}
63+
token: ${{ secrets.CODECOV_TOKEN }}
4464
- name: "Codecov: FTW"
45-
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
65+
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5
4666
if: ${{ matrix.go-version == '1.22.x' }}
4767
with:
4868
files: build/coverage-ftw.txt
49-
flags: ftw
50-
- name: "Codecov: FTW Multiphase tag"
51-
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
52-
if: ${{ matrix.go-version == '1.22.x' }}
53-
with:
54-
files: build/coverage-ftw-multiphase.txt
55-
flags: ftw-multiphase
69+
flags: ftw,${{ matrix.build-flag }}
70+
token: ${{ secrets.CODECOV_TOKEN }}
5671
- name: "Codecov: Tinygo"
57-
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
58-
if: ${{ matrix.go-version == '1.22.x' }}
72+
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5
73+
# only if coverage-tinygo.txt exists
74+
if: ${{ matrix.go-version == '1.22.x' && hashFiles('build/coverage-tinygo.txt') != '' }}
5975
with:
6076
files: build/coverage-tinygo.txt
61-
flags: tinygo
77+
flags: tinygo,${{ matrix.build-flag }}
78+
token: ${{ secrets.CODECOV_TOKEN }}

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ dictionaries to reduce memory consumption in deployments that launch several cor
104104
instances. For more context check [this issue](https://github.com/corazawaf/coraza-caddy/issues/76)
105105
* `no_fs_access` - indicates that the target environment has no access to FS in order to not leverage OS' filesystem related functionality e.g. file body buffers.
106106
* `coraza.rule.case_sensitive_args_keys` - enables case-sensitive matching for ARGS keys, aligning Coraza behavior with RFC 3986 specification. It will be enabled by default in the next major version.
107+
* `coraza.rule.no_regex_multiline` - disables enabling by default regexes multiline modifiers in `@rx` operator. It aligns with CRS expected behavior, reduces false positives and might improve performances. No multiline regexes by default will be enabled in the next major version. For more context check [this PR](https://github.com/corazawaf/coraza/pull/876)
107108

108109
## E2E Testing
109110

Diff for: experimental/plugins/macro/macro.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func (m *macro) compile(input string) error {
166166
}
167167

168168
func isValidMacroChar(c byte) bool {
169-
return c == '.' || c == '_' || c == '-' || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
169+
return c == '[' || c == ']' || c == '.' || c == '_' || c == '-' || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
170170
}
171171

172172
// String returns the original string

Diff for: experimental/plugins/macro/macro_test.go

+26-14
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ func TestCompile(t *testing.T) {
6969
})
7070

7171
t.Run("malformed macros", func(t *testing.T) {
72-
for _, test := range []string{"%{tx.count", "%{{tx.count}", "%{{tx.{count}", "something %{tx.count"} {
72+
for _, test := range []string{
73+
"%{tx.count", "%{{tx.count}", "%{{tx.{count}", "something %{tx.count",
74+
"%{ARG_NAMES:/exec/", // Wildcard variable names are not supported
75+
} {
7376
t.Run(test, func(t *testing.T) {
7477
m := &macro{}
7578
err := m.compile(test)
@@ -118,19 +121,28 @@ func TestCompile(t *testing.T) {
118121
})
119122

120123
t.Run("valid macro", func(t *testing.T) {
121-
m := &macro{}
122-
err := m.compile("%{tx.count}")
123-
if err != nil {
124-
t.Fatalf("unexpected error: %s", err.Error())
125-
}
126-
127-
if want, have := 1, len(m.tokens); want != have {
128-
t.Fatalf("unexpected number of tokens: want %d, have %d", want, have)
129-
}
130-
131-
expectedMacro := macroToken{"tx.count", variables.TX, "count"}
132-
if want, have := m.tokens[0], expectedMacro; want != have {
133-
t.Errorf("unexpected token: want %v, have %v", want, have)
124+
type testCase struct {
125+
input string
126+
expectedMacro macroToken
127+
}
128+
for _, tc := range []testCase{
129+
{"%{tx.count}", macroToken{"tx.count", variables.TX, "count"}},
130+
{"%{ARGS.exec}", macroToken{"ARGS.exec", variables.Args, "exec"}},
131+
{"%{ARGS_GET.db[]}", macroToken{"ARGS_GET.db[]", variables.ArgsGet, "db[]"}},
132+
} {
133+
m := &macro{}
134+
err := m.compile(tc.input)
135+
if err != nil {
136+
t.Fatalf("unexpected error: %s", err.Error())
137+
}
138+
139+
if len(m.tokens) != 1 {
140+
t.Fatalf("unexpected number of tokens: want %d, have %d", 1, len(m.tokens))
141+
}
142+
143+
if m.tokens[0] != tc.expectedMacro {
144+
t.Errorf("unexpected token: want %v, have %v", tc.expectedMacro, m.tokens[0])
145+
}
134146
}
135147
})
136148

Diff for: go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/corazawaf/libinjection-go v0.2.2
2323
github.com/foxcpp/go-mockdns v1.1.0
2424
github.com/jcchavezs/mergefs v0.1.0
25-
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f
25+
github.com/magefile/mage v1.15.1-0.20241126214340-bdc92f694516
2626
github.com/mccutchen/go-httpbin/v2 v2.15.0
2727
github.com/petar-dambovaliev/aho-corasick v0.0.0-20240411101913-e07a1f0e8eb4
2828
github.com/tidwall/gjson v1.18.0

Diff for: go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ github.com/jcchavezs/mergefs v0.1.0 h1:7oteO7Ocl/fnfFMkoVLJxTveCjrsd//UB0j89xmnp
1414
github.com/jcchavezs/mergefs v0.1.0/go.mod h1:eRLTrsA+vFwQZ48hj8p8gki/5v9C2bFtHH5Mnn4bcGk=
1515
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f h1:iiLWLoibjCL0XND6inF7bs2nc20lU/FYkiR//VIOLUc=
1616
github.com/magefile/mage v1.15.1-0.20231118170541-2385abb49a1f/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
17+
github.com/magefile/mage v1.15.1-0.20241124190125-32e01077f0aa h1:RAKYgtUC3OPrwUYKQcwB0wWXCHo09ZWh5TFlnF0nVfA=
18+
github.com/magefile/mage v1.15.1-0.20241124190125-32e01077f0aa/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
19+
github.com/magefile/mage v1.15.1-0.20241126214340-bdc92f694516 h1:aAO0L0ulox6m/CLRYvJff+jWXYYCKGpEm3os7dM/Z+M=
20+
github.com/magefile/mage v1.15.1-0.20241126214340-bdc92f694516/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
1721
github.com/mccutchen/go-httpbin/v2 v2.15.0 h1:3b2s8LMRR2aFd+8U+1Bx2kdgHNQ5ZQkQOiW8e52Jj9A=
1822
github.com/mccutchen/go-httpbin/v2 v2.15.0/go.mod h1:GBy5I7XwZ4ZLhT3hcq39I4ikwN9x4QUt6EAxNiR8Jus=
1923
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=

Diff for: internal/collections/map.go

+18-8
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,15 @@ func (c *Map) Get(key string) []string {
4747
if !c.isCaseSensitive {
4848
key = strings.ToLower(key)
4949
}
50-
var values []string
51-
for _, a := range c.data[key] {
52-
values = append(values, a.value)
50+
values := c.data[key]
51+
if len(values) == 0 {
52+
return nil
53+
}
54+
result := make([]string, len(values))
55+
for i, v := range values {
56+
result[i] = v.value
5357
}
54-
return values
58+
return result
5559
}
5660

5761
// FindRegex returns all map elements whose key matches the regular expression.
@@ -120,16 +124,22 @@ func (c *Map) Add(key string, value string) {
120124
c.data[key] = append(c.data[key], aVal)
121125
}
122126

123-
// Set sets the value of a key with the array of strings passed. If the key already exists, it will be overwritten.
127+
// Sets the value of a key with the array of strings passed. If the key already exists, it will be overwritten.
124128
func (c *Map) Set(key string, values []string) {
125129
originalKey := key
126130
if !c.isCaseSensitive {
127131
key = strings.ToLower(key)
128132
}
129-
c.data[key] = make([]keyValue, 0, len(values))
130-
for _, v := range values {
131-
c.data[key] = append(c.data[key], keyValue{key: originalKey, value: v})
133+
dataSlice, exists := c.data[key]
134+
if !exists || cap(dataSlice) < len(values) {
135+
dataSlice = make([]keyValue, len(values))
136+
} else {
137+
dataSlice = dataSlice[:len(values)] // Reuse existing slice with the same length
138+
}
139+
for i, v := range values {
140+
dataSlice[i] = keyValue{key: originalKey, value: v}
132141
}
142+
c.data[key] = dataSlice
133143
}
134144

135145
// SetIndex sets the value of a key at the specified index. If the key already exists, it will be overwritten.

Diff for: internal/collections/map_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,25 @@ func TestNewCaseSensitiveKeyMap(t *testing.T) {
106106
}
107107

108108
}
109+
110+
func BenchmarkTxSetGet(b *testing.B) {
111+
keys := make(map[int]string, b.N)
112+
for i := 0; i < b.N; i++ {
113+
keys[i] = fmt.Sprintf("key%d", i)
114+
}
115+
c := NewCaseSensitiveKeyMap(variables.RequestHeaders)
116+
117+
b.Run("Set", func(b *testing.B) {
118+
b.ResetTimer()
119+
for i := 0; i < b.N; i++ {
120+
c.Set(keys[i], []string{"value2"})
121+
}
122+
})
123+
b.Run("Get", func(b *testing.B) {
124+
b.ResetTimer()
125+
for i := 0; i < b.N; i++ {
126+
c.Get(keys[i])
127+
}
128+
})
129+
b.ReportAllocs()
130+
}

Diff for: internal/collections/named.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ func (c *NamedCollection) Len() int {
6161

6262
// Data is an internal method used for serializing to JSON
6363
func (c *NamedCollection) Data() map[string][]string {
64-
result := map[string][]string{}
64+
result := make(map[string][]string, len(c.data))
6565
for k, v := range c.data {
66-
result[k] = make([]string, 0, len(v))
67-
for _, a := range v {
68-
result[k] = append(result[k], a.value)
66+
result[k] = make([]string, len(v))
67+
for i, a := range v {
68+
result[k][i] = a.value
6969
}
7070
}
7171
return result

Diff for: internal/corazarules/rule_match.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,27 @@ type MatchData struct {
3333

3434
var _ types.MatchData = (*MatchData)(nil)
3535

36-
func (m *MatchData) Variable() variables.RuleVariable {
36+
func (m MatchData) Variable() variables.RuleVariable {
3737
return m.Variable_
3838
}
3939

40-
func (m *MatchData) Key() string {
40+
func (m MatchData) Key() string {
4141
return m.Key_
4242
}
4343

44-
func (m *MatchData) Value() string {
44+
func (m MatchData) Value() string {
4545
return m.Value_
4646
}
4747

48-
func (m *MatchData) Message() string {
48+
func (m MatchData) Message() string {
4949
return m.Message_
5050
}
5151

52-
func (m *MatchData) Data() string {
52+
func (m MatchData) Data() string {
5353
return m.Data_
5454
}
5555

56-
func (m *MatchData) ChainLevel() int {
56+
func (m MatchData) ChainLevel() int {
5757
return m.ChainLevel_
5858
}
5959

0 commit comments

Comments
 (0)