fix panic when decoding invalid value structure into struct

When decoding an object into a struct where the object structure doesn't
match the Go struct structure, the case tested here would panic. This
introduces additional checks to guard against the edge case being hit to
avoid the panic.

The specific checks being added are: if an item being decoded into a
struct is a literal type, the item to be decoded must be non-nil in
order to use it. This isn't super clear and to be honest I also don't
fully understand it but this fixes the problem without introducing any
more test failures and without significant code complexity.
This commit is contained in:
Mitchell Hashimoto 2016-08-21 23:44:35 -07:00
parent d8c773c4cb
commit 40a9504600
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 40 additions and 1 deletions

View File

@ -489,7 +489,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// the yacc parser would always ensure top-level elements were arrays. The new
// parser does not make the same guarantees, thus we need to convert any
// top-level literal elements into a list.
if _, ok := node.(*ast.LiteralType); ok {
if _, ok := node.(*ast.LiteralType); ok && item != nil {
node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
}

View File

@ -328,6 +328,20 @@ func TestDecode_interface(t *testing.T) {
},
},
},
// Terraform GH-8295 sanity test that basic decoding into
// interface{} works.
{
"terraform_variable_invalid.json",
false,
map[string]interface{}{
"variable": []map[string]interface{}{
map[string]interface{}{
"whatever": "abc123",
},
},
},
},
}
for _, tc := range cases {
@ -676,6 +690,26 @@ func TestDecode_structureMap(t *testing.T) {
}
}
func TestDecode_structureMapInvalid(t *testing.T) {
// Terraform GH-8295
type hclVariable struct {
Default interface{}
Description string
Fields []string `hcl:",decodedFields"`
}
type rawConfig struct {
Variable map[string]*hclVariable
}
var actual rawConfig
err := Decode(&actual, testReadFile(t, "terraform_variable_invalid.json"))
if err == nil {
t.Fatal("expected error")
}
}
func TestDecode_interfaceNonPointer(t *testing.T) {
var value interface{}
err := Decode(value, testReadFile(t, "basic_int_string.hcl"))

View File

@ -0,0 +1,5 @@
{
"variable": {
"whatever": "abc123"
}
}