From 9c2f3e9f70cd12536502f81e13298639151f6314 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Sat, 27 Sep 2025 00:04:03 +0200 Subject: [PATCH] Fix self referencing anchors should cause error (#132) --- pkg/model/anchors.go | 16 ++++++++++++---- pkg/model/anchors_test.go | 11 +++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pkg/model/anchors.go b/pkg/model/anchors.go index e68c74a7..ce4809ab 100644 --- a/pkg/model/anchors.go +++ b/pkg/model/anchors.go @@ -6,25 +6,33 @@ import ( "gopkg.in/yaml.v3" ) -// Assumes there is no cycle ensured via test TestVerifyCycleIsInvalid -func resolveAliases(node *yaml.Node) error { +func resolveAliasesExt(node *yaml.Node, path map[*yaml.Node]bool, skipCheck bool) error { + if !skipCheck && path[node] { + return errors.New("circular alias") + } switch node.Kind { case yaml.AliasNode: aliasTarget := node.Alias if aliasTarget == nil { return errors.New("unresolved alias node") } + path[node] = true *node = *aliasTarget - if err := resolveAliases(node); err != nil { + if err := resolveAliasesExt(node, path, true); err != nil { return err } + delete(path, aliasTarget) case yaml.DocumentNode, yaml.MappingNode, yaml.SequenceNode: for _, child := range node.Content { - if err := resolveAliases(child); err != nil { + if err := resolveAliasesExt(child, path, false); err != nil { return err } } } return nil } + +func resolveAliases(node *yaml.Node) error { + return resolveAliasesExt(node, map[*yaml.Node]bool{}, false) +} diff --git a/pkg/model/anchors_test.go b/pkg/model/anchors_test.go index c1fce291..0240c843 100644 --- a/pkg/model/anchors_test.go +++ b/pkg/model/anchors_test.go @@ -19,6 +19,17 @@ b: &b assert.Error(t, err) } +func TestVerifyCycleIsInvalid2(t *testing.T) { + var node yaml.Node + err := yaml.Unmarshal([]byte(` +a: &a + ref: *a +`), &node) + assert.NoError(t, err) + err = resolveAliases(&node) + assert.Error(t, err) +} + func TestVerifyNilAliasError(t *testing.T) { var node yaml.Node err := yaml.Unmarshal([]byte(`