hclpack: fix hclpack decoding nested body

Fixes an issue where a nested block would be decoded incorrectly, the
body of the last decoded block overwrites the previously decoded ones.

This was caused by the block being assigned on the stack in the for
loop; when the block is converted to a *hcl.Block, the pointer to Body
will always point to the same block. This caused decoding a new block to
overwrite the bodies of any previously decoded blocks.
This commit is contained in:
Antti Kupila 2019-01-10 08:43:00 +01:00 committed by Martin Atkins
parent 819a65acc4
commit b12d28fd16
2 changed files with 78 additions and 1 deletions

View File

@ -114,6 +114,10 @@ func (b *Body) content(schema *hcl.BodySchema, remain *Body) (*hcl.BodyContent,
var blocks []*hcl.Block
for _, block := range b.ChildBlocks {
// Redeclare block on stack so the pointer to the body is set on the
// correct block. https://github.com/hashicorp/hcl2/issues/72
block := block
blockTy := block.Type
blockS, wanted := blocksWanted[blockTy]
if !wanted {

View File

@ -75,6 +75,73 @@ func TestBodyContent(t *testing.T) {
},
},
},
"block attributes": {
&Body{
ChildBlocks: []Block{
{
Type: "foo",
Body: Body{
Attributes: map[string]Attribute{
"bar": {
Expr: Expression{
Source: []byte(`"hello"`),
SourceType: ExprNative,
},
},
},
},
},
{
Type: "foo",
Body: Body{
Attributes: map[string]Attribute{
"bar": {
Expr: Expression{
Source: []byte(`"world"`),
SourceType: ExprNative,
},
},
},
},
},
},
},
&hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{Type: "foo"},
},
},
&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "foo",
Body: &Body{
Attributes: map[string]Attribute{
"bar": {
Expr: Expression{
Source: []byte(`"hello"`),
SourceType: ExprNative,
},
},
},
},
},
{
Type: "foo",
Body: &Body{
Attributes: map[string]Attribute{
"bar": {
Expr: Expression{
Source: []byte(`"world"`),
SourceType: ExprNative,
},
},
},
},
},
},
},
},
}
for name, test := range tests {
@ -85,7 +152,13 @@ func TestBodyContent(t *testing.T) {
}
if !cmp.Equal(test.Want, got) {
t.Errorf("wrong result\n%s", cmp.Diff(test.Want, got))
bytesAsString := func(s []byte) string {
return string(s)
}
t.Errorf("wrong result\n%s", cmp.Diff(
test.Want, got,
cmp.Transformer("bytesAsString", bytesAsString),
))
}
})
}