Add logic to catch cases of alias abuse.
Backport of caeefd8.
diff --git a/decode.go b/decode.go
index e4e56e2..91679b5 100644
--- a/decode.go
+++ b/decode.go
@@ -229,6 +229,10 @@
mapType reflect.Type
terrors []string
strict bool
+
+ decodeCount int
+ aliasCount int
+ aliasDepth int
}
var (
@@ -315,6 +319,13 @@
}
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
+ d.decodeCount++
+ if d.aliasDepth > 0 {
+ d.aliasCount++
+ }
+ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > 0.99 {
+ failf("document contains excessive aliasing")
+ }
switch n.kind {
case documentNode:
return d.document(n, out)
@@ -353,7 +364,9 @@
failf("anchor '%s' value contains itself", n.value)
}
d.aliases[n] = true
+ d.aliasDepth++
good = d.unmarshal(n.alias, out)
+ d.aliasDepth--
delete(d.aliases, n)
return good
}
diff --git a/decode_test.go b/decode_test.go
index 5feaf60..a60c86b 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -854,6 +854,18 @@
{"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
{"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
+ {
+ "a: &a [00,00,00,00,00,00,00,00,00]\n" +
+ "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
+ "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
+ "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
+ "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
+ "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
+ "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
+ "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
+ "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
+ "yaml: document contains excessive aliasing",
+ },
}
func (s *S) TestUnmarshalErrors(c *C) {