|
| 1 | +From 651e204dafeecb3d4c93ed2da533b1816036ca28 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Muhammad Falak R Wani <falakreyaz@gmail.com> |
| 3 | +Date: Tue, 9 Jul 2024 21:35:27 +0530 |
| 4 | +Subject: [PATCH] decoder: limit slice creation based on configurable maxSize |
| 5 | + |
| 6 | +Fixes: GHSA-3669-72x9-r9p3 |
| 7 | +Fixes: CVE-2024-37298 |
| 8 | +Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com> |
| 9 | +--- |
| 10 | + vendor/github.com/gorilla/schema/decoder.go | 18 +++++++++++++++++- |
| 11 | + 1 file changed, 17 insertions(+), 1 deletion(-) |
| 12 | + |
| 13 | +diff --git a/vendor/github.com/gorilla/schema/decoder.go b/vendor/github.com/gorilla/schema/decoder.go |
| 14 | +index 025e438..0fd1bfe 100644 |
| 15 | +--- a/vendor/github.com/gorilla/schema/decoder.go |
| 16 | ++++ b/vendor/github.com/gorilla/schema/decoder.go |
| 17 | +@@ -12,9 +12,13 @@ import ( |
| 18 | + "strings" |
| 19 | + ) |
| 20 | + |
| 21 | ++const ( |
| 22 | ++ defaultMaxSize = 16000 |
| 23 | ++) |
| 24 | ++ |
| 25 | + // NewDecoder returns a new Decoder. |
| 26 | + func NewDecoder() *Decoder { |
| 27 | +- return &Decoder{cache: newCache()} |
| 28 | ++ return &Decoder{cache: newCache(), maxSize: defaultMaxSize} |
| 29 | + } |
| 30 | + |
| 31 | + // Decoder decodes values from a map[string][]string to a struct. |
| 32 | +@@ -22,6 +26,7 @@ type Decoder struct { |
| 33 | + cache *cache |
| 34 | + zeroEmpty bool |
| 35 | + ignoreUnknownKeys bool |
| 36 | ++ maxSize int |
| 37 | + } |
| 38 | + |
| 39 | + // SetAliasTag changes the tag used to locate custom field aliases. |
| 40 | +@@ -54,6 +59,13 @@ func (d *Decoder) IgnoreUnknownKeys(i bool) { |
| 41 | + d.ignoreUnknownKeys = i |
| 42 | + } |
| 43 | + |
| 44 | ++// MaxSize limits the size of slices for URL nested arrays or object arrays. |
| 45 | ++// Choose MaxSize carefully; large values may create many zero-value slice elements. |
| 46 | ++// Example: "items.100000=apple" would create a slice with 100,000 empty strings. |
| 47 | ++func (d *Decoder) MaxSize(size int) { |
| 48 | ++ d.maxSize = size |
| 49 | ++} |
| 50 | ++ |
| 51 | + // RegisterConverter registers a converter function for a custom type. |
| 52 | + func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) { |
| 53 | + d.cache.registerConverter(value, converterFunc) |
| 54 | +@@ -219,6 +231,10 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values |
| 55 | + // Slice of structs. Let's go recursive. |
| 56 | + if len(parts) > 1 { |
| 57 | + idx := parts[0].index |
| 58 | ++ // a defensive check to avoid creating a large slice based on user input index |
| 59 | ++ if idx > d.maxSize { |
| 60 | ++ return fmt.Errorf("%v index %d is larger than the configured maxSize %d", v.Kind(), idx, d.maxSize) |
| 61 | ++ } |
| 62 | + if v.IsNil() || v.Len() < idx+1 { |
| 63 | + value := reflect.MakeSlice(t, idx+1, idx+1) |
| 64 | + if v.Len() < idx+1 { |
| 65 | +-- |
| 66 | +2.40.1 |
| 67 | + |
0 commit comments