Просмотр исходного кода

Add logic to catch cases of alias abuse.

Backport of caeefd8.
Gustavo Niemeyer 6 лет назад
Родитель
Сommit
bb4e33bf68
2 измененных файлов с 25 добавлено и 0 удалено
  1. 13 0
      decode.go
  2. 12 0
      decode_test.go

+ 13 - 0
decode.go

@@ -229,6 +229,10 @@ type decoder struct {
 	mapType reflect.Type
 	terrors []string
 	strict  bool
+
+	decodeCount int
+	aliasCount  int
+	aliasDepth  int
 }
 
 var (
@@ -315,6 +319,13 @@ func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unm
 }
 
 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 @@ func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
 		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
 }

+ 12 - 0
decode_test.go

@@ -854,6 +854,18 @@ var unmarshalErrorTests = []struct {
 	{"{{.}}", `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) {