Procházet zdrojové kódy

rlp: fix panic in decodeList on go 1.4+

The documentation for reflect.Value.Index states that it will
panic for out-of-bounds indices. Since go 1.4, it actually panics.
Felix Lange před 11 roky
rodič
revize
c084a7daa5
1 změnil soubory, kde provedl 61 přidání a 48 odebrání
  1. 61 48
      rlp/decode.go

+ 61 - 48
rlp/decode.go

@@ -154,8 +154,6 @@ func decodeBigInt(s *Stream, val reflect.Value) error {
 	return nil
 }
 
-const maxInt = int(^uint(0) >> 1)
-
 func makeListDecoder(typ reflect.Type) (decoder, error) {
 	etype := typ.Elem()
 	if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
@@ -169,55 +167,41 @@ func makeListDecoder(typ reflect.Type) (decoder, error) {
 	if err != nil {
 		return nil, err
 	}
-	var maxLen = maxInt
+
 	if typ.Kind() == reflect.Array {
-		maxLen = typ.Len()
-	}
-	dec := func(s *Stream, val reflect.Value) error {
-		return decodeList(s, val, etypeinfo.decoder, maxLen)
+		return func(s *Stream, val reflect.Value) error {
+			return decodeListArray(s, val, etypeinfo.decoder)
+		}, nil
 	}
-	return dec, nil
+	return func(s *Stream, val reflect.Value) error {
+		return decodeListSlice(s, val, etypeinfo.decoder)
+	}, nil
 }
 
-// decodeList decodes RLP list elements into slices and arrays.
-//
-// The approach here is stolen from package json, although we differ
-// in the semantics for arrays. package json discards remaining
-// elements that would not fit into the array. We generate an error in
-// this case because we'd be losing information.
-func decodeList(s *Stream, val reflect.Value, elemdec decoder, maxelem int) error {
+func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error {
 	size, err := s.List()
 	if err != nil {
 		return err
 	}
 	if size == 0 {
-		if val.Kind() == reflect.Slice {
-			val.Set(reflect.MakeSlice(val.Type(), 0, 0))
-		} else {
-			zero(val, 0)
-		}
+		val.Set(reflect.MakeSlice(val.Type(), 0, 0))
 		return s.ListEnd()
 	}
 
 	i := 0
-	for {
-		if i > maxelem {
-			return decodeError{"input list has too many elements", val.Type()}
-		}
-		if val.Kind() == reflect.Slice {
-			// grow slice if necessary
-			if i >= val.Cap() {
-				newcap := val.Cap() + val.Cap()/2
-				if newcap < 4 {
-					newcap = 4
-				}
-				newv := reflect.MakeSlice(val.Type(), val.Len(), newcap)
-				reflect.Copy(newv, val)
-				val.Set(newv)
-			}
-			if i >= val.Len() {
-				val.SetLen(i + 1)
+	for ; ; i++ {
+		// grow slice if necessary
+		if i >= val.Cap() {
+			newcap := val.Cap() + val.Cap()/2
+			if newcap < 4 {
+				newcap = 4
 			}
+			newv := reflect.MakeSlice(val.Type(), val.Len(), newcap)
+			reflect.Copy(newv, val)
+			val.Set(newv)
+		}
+		if i >= val.Len() {
+			val.SetLen(i + 1)
 		}
 		// decode into element
 		if err := elemdec(s, val.Index(i)); err == EOL {
@@ -225,26 +209,54 @@ func decodeList(s *Stream, val reflect.Value, elemdec decoder, maxelem int) erro
 		} else if err != nil {
 			return err
 		}
-		i++
 	}
 	if i < val.Len() {
-		if val.Kind() == reflect.Array {
-			// zero the rest of the array.
-			zero(val, i)
-		} else {
-			val.SetLen(i)
-		}
+		val.SetLen(i)
 	}
 	return s.ListEnd()
 }
 
+func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error {
+	size, err := s.List()
+	if err != nil {
+		return err
+	}
+	if size == 0 {
+		zero(val, 0)
+		return s.ListEnd()
+	}
+
+	// The approach here is stolen from package json, although we differ
+	// in the semantics for arrays. package json discards remaining
+	// elements that would not fit into the array. We generate an error in
+	// this case because we'd be losing information.
+	vlen := val.Len()
+	i := 0
+	for ; i < vlen; i++ {
+		if err := elemdec(s, val.Index(i)); err == EOL {
+			break
+		} else if err != nil {
+			return err
+		}
+		if i == vlen {
+		}
+	}
+	if i < vlen {
+		zero(val, i)
+	}
+	if err = s.ListEnd(); err == errNotAtEOL {
+		return decodeError{"input list has too many elements", val.Type()}
+	}
+	return err
+}
+
 func decodeByteSlice(s *Stream, val reflect.Value) error {
 	kind, _, err := s.Kind()
 	if err != nil {
 		return err
 	}
 	if kind == List {
-		return decodeList(s, val, decodeUint, maxInt)
+		return decodeListSlice(s, val, decodeUint)
 	}
 	b, err := s.Bytes()
 	if err == nil {
@@ -276,14 +288,15 @@ func decodeByteArray(s *Stream, val reflect.Value) error {
 		}
 		zero(val, int(size))
 	case List:
-		return decodeList(s, val, decodeUint, val.Len())
+		return decodeListArray(s, val, decodeUint)
 	}
 	return nil
 }
 
 func zero(val reflect.Value, start int) {
 	z := reflect.Zero(val.Type().Elem())
-	for i := start; i < val.Len(); i++ {
+	end := val.Len()
+	for i := start; i < end; i++ {
 		val.Index(i).Set(z)
 	}
 }
@@ -358,7 +371,7 @@ func decodeInterface(s *Stream, val reflect.Value) error {
 	}
 	if kind == List {
 		slice := reflect.New(ifsliceType).Elem()
-		if err := decodeList(s, slice, decodeInterface, maxInt); err != nil {
+		if err := decodeListSlice(s, slice, decodeInterface); err != nil {
 			return err
 		}
 		val.Set(slice)