Skip to content

Commit 5296850

Browse files
authored
support for nil and invalid value in the encoding tree (#42)
- [x] Replace nil errors by nil wafObject values - [x] Replace invalid types by invalid wafObject values - [x] Remove most errors from encoder functions - [x] Keep map key even if the encoded value is nil or invalid - [x] Keep struct field even if the encoded value is nil or invalid - [x] Discard nil or invalid wafObject in arrays - [x] Change current tests to match new implemntation - [x] Write Run() tests to check if the waf supported these types - [x] Refactor `EncoderTest` testsuite because it does not test was we would like anymore --------- Signed-off-by: Eliott Bouhana <[email protected]>
1 parent f4a6958 commit 5296850

File tree

8 files changed

+869
-965
lines changed

8 files changed

+869
-965
lines changed

context.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -85,27 +85,15 @@ func (context *Context) Run(addressData RunAddressData, timeout time.Duration) (
8585
context.totalOverallRuntimeNs.Add(uint64(dt.Nanoseconds()))
8686
}()
8787

88-
persistentEncoder := encoder{
89-
stringMaxSize: wafMaxStringLength,
90-
containerMaxSize: wafMaxContainerSize,
91-
objectMaxDepth: wafMaxContainerDepth,
92-
}
93-
persistentData, err := persistentEncoder.Encode(addressData.Persistent)
94-
if err != nil {
95-
return res, err
96-
}
88+
// We can ignore the encoding error because it can only tell us that the user values are incompatible with the WAF
89+
// which is not something we care about here.
90+
persistentEncoder := newLimitedEncoder()
91+
persistentData, _ := persistentEncoder.Encode(addressData.Persistent)
9792

9893
// The WAF releases ephemeral address data at the end of each run call, so we need not keep the Go values live beyond
9994
// that in the same way we need for persistent data. We hence use a separate encoder.
100-
ephemeralEncoder := encoder{
101-
stringMaxSize: wafMaxStringLength,
102-
containerMaxSize: wafMaxContainerSize,
103-
objectMaxDepth: wafMaxContainerDepth,
104-
}
105-
ephemeralData, err := ephemeralEncoder.Encode(addressData.Ephemeral)
106-
if err != nil {
107-
return res, err
108-
}
95+
ephemeralEncoder := newLimitedEncoder()
96+
ephemeralData, _ := ephemeralEncoder.Encode(addressData.Ephemeral)
10997

11098
// ddwaf_run cannot run concurrently and the next append write on the context state so we need a mutex
11199
context.mutex.Lock()

ctypes.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ type wafObject struct {
5858
// packed (apart from breaking all tracers of course)
5959
}
6060

61+
// isNil determines whether this WAF Object is nil or not.
62+
func (w *wafObject) isNil() bool {
63+
return w._type == wafNilType
64+
}
65+
6166
// isArray determines whether this WAF Object is an array or not.
6267
func (w *wafObject) isArray() bool {
6368
return w._type == wafArrayType
@@ -68,6 +73,12 @@ func (w *wafObject) isMap() bool {
6873
return w._type == wafMapType
6974
}
7075

76+
// IsUnusable returns true if the wafObject has no impact on the WAF execution
77+
// But we still need this kind of objects to forward map keys in case the value of the map is invalid
78+
func (wo *wafObject) IsUnusable() bool {
79+
return wo._type == wafInvalidType || wo._type == wafNilType
80+
}
81+
7182
type wafConfig struct {
7283
limits wafConfigLimits
7384
obfuscator wafConfigObfuscator

decoder.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ func decodeErrors(obj *wafObject) (map[string][]string, error) {
1919
wafErrors := map[string][]string{}
2020
for i := uint64(0); i < obj.nbEntries; i++ {
2121
objElem := castWithOffset[wafObject](obj.value, i)
22-
if objElem._type != wafArrayType {
23-
return nil, errInvalidObjectType
24-
}
2522

2623
errorMessage := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength)
2724
ruleIds, err := decodeStringArray(objElem)
@@ -141,6 +138,11 @@ func decodeDiagnosticAddresses(obj *wafObject) (res DiagnosticAddresses, err err
141138
}
142139

143140
func decodeStringArray(obj *wafObject) ([]string, error) {
141+
// We consider that nil is an empty array
142+
if obj.isNil() {
143+
return nil, nil
144+
}
145+
144146
if !obj.isArray() {
145147
return nil, errInvalidObjectType
146148
}
@@ -178,12 +180,18 @@ func decodeObject(obj *wafObject) (any, error) {
178180
return uintptrToNative[float64](obj.value), nil
179181
case wafBoolType:
180182
return uintptrToNative[bool](obj.value), nil
183+
case wafNilType:
184+
return nil, nil
181185
default:
182186
return nil, errUnsupportedValue
183187
}
184188
}
185189

186190
func decodeArray(obj *wafObject) ([]any, error) {
191+
if obj.isNil() {
192+
return nil, nil
193+
}
194+
187195
if !obj.isArray() {
188196
return nil, errInvalidObjectType
189197
}
@@ -203,6 +211,10 @@ func decodeArray(obj *wafObject) ([]any, error) {
203211
}
204212

205213
func decodeMap(obj *wafObject) (map[string]any, error) {
214+
if obj.isNil() {
215+
return nil, nil
216+
}
217+
206218
if !obj.isMap() {
207219
return nil, errInvalidObjectType
208220
}

decoder_test.go

Lines changed: 0 additions & 150 deletions
This file was deleted.

0 commit comments

Comments
 (0)