ソースを参照

Add logic to catch cases of alias abuse.

Gustavo Niemeyer 6 年 前
コミット
caeefd850a
2 ファイル変更24 行追加0 行削除
  1. 12 0
      decode.go
  2. 12 0
      decode_test.go

+ 12 - 0
decode.go

@@ -309,6 +309,9 @@ type decoder struct {
 
 	knownFields bool
 	uniqueKeys  bool
+	decodeCount int
+	aliasCount  int
+	aliasDepth  int
 }
 
 var (
@@ -432,6 +435,13 @@ func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field ref
 }
 
 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")
+	}
 	if out.Type() == nodeType {
 		out.Set(reflect.ValueOf(n).Elem())
 		return true
@@ -474,7 +484,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

@@ -911,6 +911,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) {