Repository: helm/helm (go)

Issue:
Helm template throws stack overflow error
**Describe the bug**
We have the following example values.yaml file for helm chart:
```
dashboards:
 clustersmonitoringjson:
   {

         "select": [
            [
              {
                "params": [
                  "status"
                ],
                "type": "field"
              }
            ]
         ]
    }
```
If I want to pass them through `helm template  --set` command stack overflow error is thrown.

Helm command:
```
helm template . --namespace default --set dashboards.clustersmonitoringjson.select[0][0].params[0]=status --set dashboards.clustersmonitoringjson.select[0][0].type=field --name helmguestbook
```
Error thrown:

```
runtime: goroutine stack exceeds 1000000000-byte limit\nfatal error: stack overflow\n\nruntime stack:\nruntime.throw(0x16a2c72, 0xe)\n\t/usr/local/go/src/runtime/panic.go:608 +0x72\nruntime.newstack()\n\t/usr/local/go/src/runtime/stack.go:1008 +0x729\nruntime.morestack()\n\t/usr/local/go/src/runtime/asm_amd64.s:429 +0x8f\n\ngoroutine 1 [running]:\nruntime.efaceeq(0x1660160, 0x141ad00, 0x141ad00, 0x0)\n\t/usr/local/go/src/runtime/alg.go:218 +0x131 fp=0xc0209b0358 sp=0xc0209b0350 pc=0x403631\nruntime.nilinterequal(0xc0209b0448, 0xc00047e848, 0xc5b27c6c1b7408fc)\n\t/usr/local/go/src/runtime/alg.go:216 +0x5d fp=0xc0209b0388 sp=0xc0209b0358 pc=0x4034ed\nruntime.mapaccess2(0x14a80a0, 0xc000509530, 0xc0209b0448, 0x0, 0x0)\n\t/usr/local/go/src/runtime/map.go:479 +0x146 fp=0xc0209b03d0 sp=0xc0209b0388 pc=0x40d646\nsync.(*Map).Load(0x2729c00, 0x1660160, 0x141ad
```

It can be tested with any chart. This error does not depend on the chart itself.
The issue is not reproducible if parameters are separated by commas in one --set parameters. 



Pull request:
fix stack overflow error in helm template.
fix #6116

When value has a nested list in "helm template --set" cmd and the nested list already has a value, it may becomes endless nested list. And it will result in stack overflow.

My solution is to judge the nested list if it already has a value, and if it is yes, take the value of list to next cycle.

Patch:
diff --git a/pkg/strvals/parser.go b/pkg/strvals/parser.go
index c735412e9..457b99f94 100644
--- a/pkg/strvals/parser.go
+++ b/pkg/strvals/parser.go
@@ -301,12 +301,20 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
 		}
 	case last == '[':
 		// now we have a nested list. Read the index and handle.
-		i, err := t.keyIndex()
+		nextI, err := t.keyIndex()
 		if err != nil {
 			return list, errors.Wrap(err, "error parsing index")
 		}
+		var crtList []interface{}
+		if len(list) > i {
+			// If nested list already exists, take the value of list to next cycle.
+			existed := list[i]
+			if existed != nil {
+				crtList = list[i].([]interface{})
+			}
+		}
 		// Now we need to get the value after the ].
-		list2, err := t.listItem(list, i)
+		list2, err := t.listItem(crtList, nextI)
 		if err != nil {
 			return list, err
 		}


Test patch:
diff --git a/pkg/strvals/parser_test.go b/pkg/strvals/parser_test.go
index 742256153..cef98ba0a 100644
--- a/pkg/strvals/parser_test.go
+++ b/pkg/strvals/parser_test.go
@@ -421,39 +421,118 @@ func TestParseSet(t *testing.T) {
 }
 
 func TestParseInto(t *testing.T) {
-	got := map[string]interface{}{
-		"outer": map[string]interface{}{
-			"inner1": "overwrite",
-			"inner2": "value2",
+	tests := []struct {
+		input  string
+		input2 string
+		got    map[string]interface{}
+		expect map[string]interface{}
+		err    bool
+	}{
+		{
+			input: "outer.inner1=value1,outer.inner3=value3,outer.inner4=4",
+			got: map[string]interface{}{
+				"outer": map[string]interface{}{
+					"inner1": "overwrite",
+					"inner2": "value2",
+				},
+			},
+			expect: map[string]interface{}{
+				"outer": map[string]interface{}{
+					"inner1": "value1",
+					"inner2": "value2",
+					"inner3": "value3",
+					"inner4": 4,
+				}},
+			err: false,
 		},
-	}
-	input := "outer.inner1=value1,outer.inner3=value3,outer.inner4=4"
-	expect := map[string]interface{}{
-		"outer": map[string]interface{}{
-			"inner1": "value1",
-			"inner2": "value2",
-			"inner3": "value3",
-			"inner4": 4,
+		{
+			input:  "listOuter[0][0].type=listValue",
+			input2: "listOuter[0][0].status=alive",
+			got:    map[string]interface{}{},
+			expect: map[string]interface{}{
+				"listOuter": [][]interface{}{{map[string]string{
+					"type":   "listValue",
+					"status": "alive",
+				}}},
+			},
+			err: false,
+		},
+		{
+			input:  "listOuter[0][0].type=listValue",
+			input2: "listOuter[1][0].status=alive",
+			got:    map[string]interface{}{},
+			expect: map[string]interface{}{
+				"listOuter": [][]interface{}{
+					{
+						map[string]string{"type": "listValue"},
+					},
+					{
+						map[string]string{"status": "alive"},
+					},
+				},
+			},
+			err: false,
+		},
+		{
+			input:  "listOuter[0][1][0].type=listValue",
+			input2: "listOuter[0][0][1].status=alive",
+			got: map[string]interface{}{
+				"listOuter": []interface{}{
+					[]interface{}{
+						[]interface{}{
+							map[string]string{"exited": "old"},
+						},
+					},
+				},
+			},
+			expect: map[string]interface{}{
+				"listOuter": [][][]interface{}{
+					{
+						{
+							map[string]string{"exited": "old"},
+							map[string]string{"status": "alive"},
+						},
+						{
+							map[string]string{"type": "listValue"},
+						},
+					},
+				},
+			},
+			err: false,
 		},
 	}
+	for _, tt := range tests {
+		if err := ParseInto(tt.input, tt.got); err != nil {
+			t.Fatal(err)
+		}
+		if tt.err {
+			t.Errorf("%s: Expected error. Got nil", tt.input)
+		}
 
-	if err := ParseInto(input, got); err != nil {
-		t.Fatal(err)
-	}
+		if tt.input2 != "" {
+			if err := ParseInto(tt.input2, tt.got); err != nil {
+				t.Fatal(err)
+			}
+			if tt.err {
+				t.Errorf("%s: Expected error. Got nil", tt.input2)
+			}
+		}
 
-	y1, err := yaml.Marshal(expect)
-	if err != nil {
-		t.Fatal(err)
-	}
-	y2, err := yaml.Marshal(got)
-	if err != nil {
-		t.Fatalf("Error serializing parsed value: %s", err)
-	}
+		y1, err := yaml.Marshal(tt.expect)
+		if err != nil {
+			t.Fatal(err)
+		}
+		y2, err := yaml.Marshal(tt.got)
+		if err != nil {
+			t.Fatalf("Error serializing parsed value: %s", err)
+		}
 
-	if string(y1) != string(y2) {
-		t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2)
+		if string(y1) != string(y2) {
+			t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.input, y1, y2)
+		}
 	}
 }
+
 func TestParseIntoString(t *testing.T) {
 	got := map[string]interface{}{
 		"outer": map[string]interface{}{