Skip to content

Commit 3636f68

Browse files
authored
Merge pull request from GHSA-6rx9-889q-vv2r
Update string value name handling
2 parents 638ebff + b6fef6c commit 3636f68

File tree

2 files changed

+83
-9
lines changed

2 files changed

+83
-9
lines changed

pkg/strvals/parser.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ var ErrNotList = errors.New("not a list")
3636
// The default value 65536 = 1024 * 64
3737
var MaxIndex = 65536
3838

39+
// MaxNestedNameLevel is the maximum level of nesting for a value name that
40+
// will be allowed.
41+
var MaxNestedNameLevel = 30
42+
3943
// ToYAML takes a string of arguments and converts to a YAML document.
4044
func ToYAML(s string) (string, error) {
4145
m, err := Parse(s)
@@ -155,7 +159,7 @@ func newFileParser(sc *bytes.Buffer, data map[string]interface{}, reader RunesVa
155159

156160
func (t *parser) parse() error {
157161
for {
158-
err := t.key(t.data)
162+
err := t.key(t.data, 0)
159163
if err == nil {
160164
continue
161165
}
@@ -174,7 +178,7 @@ func runeSet(r []rune) map[rune]bool {
174178
return s
175179
}
176180

177-
func (t *parser) key(data map[string]interface{}) (reterr error) {
181+
func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr error) {
178182
defer func() {
179183
if r := recover(); r != nil {
180184
reterr = fmt.Errorf("unable to parse key: %s", r)
@@ -204,7 +208,7 @@ func (t *parser) key(data map[string]interface{}) (reterr error) {
204208
}
205209

206210
// Now we need to get the value after the ].
207-
list, err = t.listItem(list, i)
211+
list, err = t.listItem(list, i, nestedNameLevel)
208212
set(data, kk, list)
209213
return err
210214
case last == '=':
@@ -261,18 +265,26 @@ func (t *parser) key(data map[string]interface{}) (reterr error) {
261265
set(data, string(k), "")
262266
return errors.Errorf("key %q has no value (cannot end with ,)", string(k))
263267
case last == '.':
268+
// Check value name is within the maximum nested name level
269+
nestedNameLevel++
270+
if nestedNameLevel > MaxNestedNameLevel {
271+
return fmt.Errorf("value name nested level is greater than maximum supported nested level of %d", MaxNestedNameLevel)
272+
}
273+
264274
// First, create or find the target map.
265275
inner := map[string]interface{}{}
266276
if _, ok := data[string(k)]; ok {
267277
inner = data[string(k)].(map[string]interface{})
268278
}
269279

270280
// Recurse
271-
e := t.key(inner)
272-
if len(inner) == 0 {
281+
e := t.key(inner, nestedNameLevel)
282+
if e == nil && len(inner) == 0 {
273283
return errors.Errorf("key map %q has no value", string(k))
274284
}
275-
set(data, string(k), inner)
285+
if len(inner) != 0 {
286+
set(data, string(k), inner)
287+
}
276288
return e
277289
}
278290
}
@@ -322,7 +334,7 @@ func (t *parser) keyIndex() (int, error) {
322334
return strconv.Atoi(string(v))
323335

324336
}
325-
func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
337+
func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interface{}, error) {
326338
if i < 0 {
327339
return list, fmt.Errorf("negative %d index not allowed", i)
328340
}
@@ -395,7 +407,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
395407
}
396408
}
397409
// Now we need to get the value after the ].
398-
list2, err := t.listItem(crtList, nextI)
410+
list2, err := t.listItem(crtList, nextI, nestedNameLevel)
399411
if err != nil {
400412
return list, err
401413
}
@@ -414,7 +426,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
414426
}
415427

416428
// Recurse
417-
e := t.key(inner)
429+
e := t.key(inner, nestedNameLevel)
418430
if e != nil {
419431
return list, e
420432
}

pkg/strvals/parser_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616
package strvals
1717

1818
import (
19+
"fmt"
1920
"testing"
2021

2122
"sigs.k8s.io/yaml"
@@ -754,3 +755,64 @@ func TestToYAML(t *testing.T) {
754755
t.Errorf("Expected %q, got %q", expect, o)
755756
}
756757
}
758+
759+
func TestParseSetNestedLevels(t *testing.T) {
760+
var keyMultipleNestedLevels string
761+
for i := 1; i <= MaxNestedNameLevel+2; i++ {
762+
tmpStr := fmt.Sprintf("name%d", i)
763+
if i <= MaxNestedNameLevel+1 {
764+
tmpStr = tmpStr + "."
765+
}
766+
keyMultipleNestedLevels += tmpStr
767+
}
768+
tests := []struct {
769+
str string
770+
expect map[string]interface{}
771+
err bool
772+
errStr string
773+
}{
774+
{
775+
"outer.middle.inner=value",
776+
map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}},
777+
false,
778+
"",
779+
},
780+
{
781+
str: keyMultipleNestedLevels + "=value",
782+
err: true,
783+
errStr: fmt.Sprintf("value name nested level is greater than maximum supported nested level of %d",
784+
MaxNestedNameLevel),
785+
},
786+
}
787+
788+
for _, tt := range tests {
789+
got, err := Parse(tt.str)
790+
if err != nil {
791+
if tt.err {
792+
if tt.errStr != "" {
793+
if err.Error() != tt.errStr {
794+
t.Errorf("Expected error: %s. Got error: %s", tt.errStr, err.Error())
795+
}
796+
}
797+
continue
798+
}
799+
t.Fatalf("%s: %s", tt.str, err)
800+
}
801+
if tt.err {
802+
t.Errorf("%s: Expected error. Got nil", tt.str)
803+
}
804+
805+
y1, err := yaml.Marshal(tt.expect)
806+
if err != nil {
807+
t.Fatal(err)
808+
}
809+
y2, err := yaml.Marshal(got)
810+
if err != nil {
811+
t.Fatalf("Error serializing parsed value: %s", err)
812+
}
813+
814+
if string(y1) != string(y2) {
815+
t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.str, y1, y2)
816+
}
817+
}
818+
}

0 commit comments

Comments
 (0)