forked from cerc-io/plugeth
		
	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.
This commit is contained in:
		
							parent
							
								
									93e858f88e
								
							
						
					
					
						commit
						c084a7daa5
					
				
							
								
								
									
										109
									
								
								rlp/decode.go
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								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() | ||||
| 		return func(s *Stream, val reflect.Value) error { | ||||
| 			return decodeListArray(s, val, etypeinfo.decoder) | ||||
| 		}, nil | ||||
| 	} | ||||
| 	dec := func(s *Stream, val reflect.Value) error { | ||||
| 		return decodeList(s, val, etypeinfo.decoder, maxLen) | ||||
| 	} | ||||
| 	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()} | ||||
| 	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 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) | ||||
| 			} | ||||
| 		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) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user