Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion libs/dyn/yamlloader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ func (e *LocationError) Error() string {

type loader struct {
path string

// Aliases currently being expanded. A self-referential anchor (e.g.
// "a: &x {b: *x}") makes the yaml.v3 node graph cyclic; without this
// bookkeeping, expansion would recurse until stack overflow.
activeAliases map[*yaml.Node]bool
}

func errorf(loc dyn.Location, format string, args ...any) error {
Expand All @@ -31,7 +36,8 @@ func errorf(loc dyn.Location, format string, args ...any) error {

func newLoader(path string) *loader {
return &loader{
path: path,
path: path,
activeAliases: make(map[*yaml.Node]bool),
}
}

Expand Down Expand Up @@ -271,5 +277,14 @@ func (d *loader) loadScalar(node *yaml.Node, loc dyn.Location) (dyn.Value, error
}

func (d *loader) loadAlias(node *yaml.Node, loc dyn.Location) (dyn.Value, error) {
if d.activeAliases[node] {
return dyn.InvalidValue, errorf(loc, "cyclic reference to anchor %q", node.Value)
}

// The same alias node may be reached again through another alias to an
// enclosing anchor, which is not a cycle.
d.activeAliases[node] = true
defer delete(d.activeAliases, node)

return d.load(node.Alias)
}
2 changes: 2 additions & 0 deletions libs/dyn/yamlloader/testdata/anchor_09.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
anchortest: &x
child: *x
5 changes: 5 additions & 0 deletions libs/dyn/yamlloader/testdata/anchor_10.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
leaf: &leaf 1
shared: &shared
value: *leaf
use1: *shared
use2: *shared
22 changes: 22 additions & 0 deletions libs/dyn/yamlloader/yaml_anchor_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package yamlloader_test

import (
"bytes"
"os"
"testing"

"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/dyn/yamlloader"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestYAMLAnchor01(t *testing.T) {
Expand Down Expand Up @@ -115,3 +119,21 @@ func TestYAMLAnchor08(t *testing.T) {
assert.Equal(t, true, active.AsAny())
assert.Equal(t, dyn.Location{File: file, Line: 2, Column: 11}, active.Location())
}

func TestYAMLAnchor09(t *testing.T) {
file := "testdata/anchor_09.yml"
input, err := os.ReadFile(file)
require.NoError(t, err)

_, err = yamlloader.LoadYAML(file, bytes.NewBuffer(input))
assert.ErrorContains(t, err, `cyclic reference to anchor "x"`)
}

func TestYAMLAnchor10(t *testing.T) {
file := "testdata/anchor_10.yml"
self := loadYAML(t, file)
assert.NotEqual(t, dyn.NilValue, self)

assert.Equal(t, 1, self.Get("use1").Get("value").AsAny())
assert.Equal(t, 1, self.Get("use2").Get("value").AsAny())
}
Loading