Skip to content

Commit 88ca71b

Browse files
idsulikglours
authored andcommitted
fix(reset): Add cycle detector in reset.go
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
1 parent 156e22d commit 88ca71b

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

loader/reset.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ import (
2626
)
2727

2828
type ResetProcessor struct {
29-
target interface{}
30-
paths []tree.Path
29+
target interface{}
30+
paths []tree.Path
31+
visitedNodes map[*yaml.Node]bool
3132
}
3233

3334
// UnmarshalYAML implement yaml.Unmarshaler
3435
func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
3536
resolved, err := p.resolveReset(value, tree.NewPath())
37+
p.visitedNodes = nil
3638
if err != nil {
3739
return err
3840
}
@@ -45,6 +47,20 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No
4547
if strings.Contains(path.String(), ".<<") {
4648
path = tree.NewPath(strings.Replace(path.String(), ".<<", "", 1))
4749
}
50+
51+
// Check for cycle
52+
if p.visitedNodes == nil {
53+
p.visitedNodes = make(map[*yaml.Node]bool)
54+
}
55+
56+
// Check if the current node has been visited before (cycle detection)
57+
if p.visitedNodes[node] {
58+
return nil, fmt.Errorf("cycle detected at path: %s", path.String())
59+
}
60+
61+
// Mark the current node as visited
62+
p.visitedNodes[node] = true
63+
4864
// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
4965
if node.Kind == yaml.AliasNode {
5066
return p.resolveReset(node.Alias, path)

loader/reset_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,24 @@ networks:
8181
assert.NilError(t, err)
8282
assert.Check(t, p.Networks["test"].External == false)
8383
}
84+
85+
func TestResetCycle(t *testing.T) {
86+
_, err := Load(
87+
types.ConfigDetails{
88+
ConfigFiles: []types.ConfigFile{
89+
{
90+
Filename: "(inline)",
91+
Content: []byte(`
92+
x-healthcheck: &healthcheck
93+
egress-service:
94+
<<: *healthcheck
95+
`),
96+
},
97+
},
98+
}, func(options *Options) {
99+
options.SkipNormalization = true
100+
options.SkipConsistencyCheck = true
101+
},
102+
)
103+
assert.Error(t, err, "cycle detected at path: x-healthcheck.egress-service")
104+
}

0 commit comments

Comments
 (0)