seen: check inline tables (#660)

Fixes #658
This commit is contained in:
Thomas Pelletier
2021-11-08 21:53:02 -05:00
committed by GitHub
parent dc1740d473
commit 8683be35f6
2 changed files with 30 additions and 9 deletions
+24 -9
View File
@@ -65,7 +65,7 @@ type entry struct {
explicit bool explicit bool
} }
// Remove all descendent of node at position idx. // Remove all descendants of node at position idx.
func (s *SeenTracker) clear(idx int) { func (s *SeenTracker) clear(idx int) {
p := s.entries[idx].id p := s.entries[idx].id
rest := clear(p, s.entries[idx+1:]) rest := clear(p, s.entries[idx+1:])
@@ -102,19 +102,21 @@ func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit
return idx return idx
} }
// CheckExpression takes a top-level node and checks that it does not contain keys // CheckExpression takes a top-level node and checks that it does not contain
// that have been seen in previous calls, and validates that types are consistent. // keys that have been seen in previous calls, and validates that types are
// consistent.
func (s *SeenTracker) CheckExpression(node *ast.Node) error { func (s *SeenTracker) CheckExpression(node *ast.Node) error {
if s.entries == nil { if s.entries == nil {
// Skip ID = 0 to remove the confusion between nodes whose parent has // Skip ID = 0 to remove the confusion between nodes whose
// id 0 and root nodes (parent id is 0 because it's the zero value). // parent has id 0 and root nodes (parent id is 0 because it's
// the zero value).
s.nextID = 1 s.nextID = 1
// Start unscoped, so idx is negative. // Start unscoped, so idx is negative.
s.currentIdx = -1 s.currentIdx = -1
} }
switch node.Kind { switch node.Kind {
case ast.KeyValue: case ast.KeyValue:
return s.checkKeyValue(node) return s.checkKeyValue(s.currentIdx, node)
case ast.Table: case ast.Table:
return s.checkTable(node) return s.checkTable(node)
case ast.ArrayTable: case ast.ArrayTable:
@@ -206,11 +208,9 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
return nil return nil
} }
func (s *SeenTracker) checkKeyValue(node *ast.Node) error { func (s *SeenTracker) checkKeyValue(parentIdx int, node *ast.Node) error {
it := node.Key() it := node.Key()
parentIdx := s.currentIdx
for it.Next() { for it.Next() {
k := it.Node().Data k := it.Node().Data
@@ -230,12 +230,27 @@ func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
} }
kind := valueKind kind := valueKind
var err error
if node.Value().Kind == ast.InlineTable { if node.Value().Kind == ast.InlineTable {
kind = tableKind kind = tableKind
err = s.checkInlineTable(parentIdx, node.Value())
} }
s.entries[parentIdx].kind = kind s.entries[parentIdx].kind = kind
return err
}
func (s *SeenTracker) checkInlineTable(parentIdx int, node *ast.Node) error {
it := node.Children()
for it.Next() {
n := it.Node()
err := s.checkKeyValue(parentIdx, n)
if err != nil {
return err
}
}
return nil return nil
} }
+6
View File
@@ -1910,6 +1910,12 @@ func TestIssue564(t *testing.T) {
require.Equal(t, uuid{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, config.ID) require.Equal(t, uuid{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, config.ID)
} }
func TestIssue658(t *testing.T) {
var v map[string]interface{}
err := toml.Unmarshal([]byte("e={b=1,b=4}"), &v)
require.Error(t, err)
}
//nolint:funlen //nolint:funlen
func TestUnmarshalDecodeErrors(t *testing.T) { func TestUnmarshalDecodeErrors(t *testing.T) {
examples := []struct { examples := []struct {