Decoder: prevent modification of inline tables (#702)

Fixes #701
This commit is contained in:
Thomas Pelletier
2021-12-12 09:43:42 -05:00
committed by GitHub
parent 8bbb519477
commit facb2b13e8
2 changed files with 47 additions and 1 deletions
+19
View File
@@ -145,6 +145,11 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
if idx < 0 { if idx < 0 {
idx = s.create(parentIdx, k, tableKind, false) idx = s.create(parentIdx, k, tableKind, false)
} else {
entry := s.entries[idx]
if entry.kind == valueKind {
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
}
} }
parentIdx = idx parentIdx = idx
} }
@@ -186,7 +191,13 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
if idx < 0 { if idx < 0 {
idx = s.create(parentIdx, k, tableKind, false) idx = s.create(parentIdx, k, tableKind, false)
} else {
entry := s.entries[idx]
if entry.kind == valueKind {
return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
}
} }
parentIdx = idx parentIdx = idx
} }
@@ -281,6 +292,14 @@ func (s *SeenTracker) checkInlineTable(parentIdx int, node *ast.Node) error {
return err return err
} }
} }
// As inline tables are self-contained, the tracker does not
// need to retain the details of what they contain. The
// keyValue element that creates the inline table is kept to
// mark the presence of the inline table and prevent
// redefinition of its keys: check* functions cannot walk into
// a value.
s.clear(parentIdx)
return nil return nil
} }
+28 -1
View File
@@ -2270,7 +2270,34 @@ Program = "hugo"
require.Equal(t, expected, p) require.Equal(t, expected, p)
} }
//nolint:funlen func TestIssue701(t *testing.T) {
// Expected behavior:
// Return an error since a cannot be modified. From the TOML spec:
//
// > Inline tables are fully self-contained and define all
// keys and sub-tables within them. Keys and sub-tables cannot
// be added outside the braces.
docs := []string{
`
a={}
[a.b]
z=0
`,
`
a={}
[[a.b]]
z=0
`,
}
for _, doc := range docs {
var v interface{}
err := toml.Unmarshal([]byte(doc), &v)
assert.Error(t, err)
}
}
func TestUnmarshalDecodeErrors(t *testing.T) { func TestUnmarshalDecodeErrors(t *testing.T) {
examples := []struct { examples := []struct {
desc string desc string