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
					
				| @ -154,8 +154,6 @@ func decodeBigInt(s *Stream, val reflect.Value) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const maxInt = int(^uint(0) >> 1) |  | ||||||
| 
 |  | ||||||
| func makeListDecoder(typ reflect.Type) (decoder, error) { | func makeListDecoder(typ reflect.Type) (decoder, error) { | ||||||
| 	etype := typ.Elem() | 	etype := typ.Elem() | ||||||
| 	if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) { | 	if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) { | ||||||
| @ -169,42 +167,29 @@ func makeListDecoder(typ reflect.Type) (decoder, error) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	var maxLen = maxInt | 
 | ||||||
| 	if typ.Kind() == reflect.Array { | 	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 func(s *Stream, val reflect.Value) error { | ||||||
| 		return decodeList(s, val, etypeinfo.decoder, maxLen) | 		return decodeListSlice(s, val, etypeinfo.decoder) | ||||||
| 	} | 	}, nil | ||||||
| 	return dec, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // decodeList decodes RLP list elements into slices and arrays.
 | func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error { | ||||||
| //
 |  | ||||||
| // 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 { |  | ||||||
| 	size, err := s.List() | 	size, err := s.List() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if size == 0 { | 	if size == 0 { | ||||||
| 		if val.Kind() == reflect.Slice { |  | ||||||
| 		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) | 		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) | ||||||
| 		} else { |  | ||||||
| 			zero(val, 0) |  | ||||||
| 		} |  | ||||||
| 		return s.ListEnd() | 		return s.ListEnd() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	i := 0 | 	i := 0 | ||||||
| 	for { | 	for ; ; i++ { | ||||||
| 		if i > maxelem { |  | ||||||
| 			return decodeError{"input list has too many elements", val.Type()} |  | ||||||
| 		} |  | ||||||
| 		if val.Kind() == reflect.Slice { |  | ||||||
| 		// grow slice if necessary
 | 		// grow slice if necessary
 | ||||||
| 		if i >= val.Cap() { | 		if i >= val.Cap() { | ||||||
| 			newcap := val.Cap() + val.Cap()/2 | 			newcap := val.Cap() + val.Cap()/2 | ||||||
| @ -218,33 +203,60 @@ func decodeList(s *Stream, val reflect.Value, elemdec decoder, maxelem int) erro | |||||||
| 		if i >= val.Len() { | 		if i >= val.Len() { | ||||||
| 			val.SetLen(i + 1) | 			val.SetLen(i + 1) | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 		// decode into element
 | 		// decode into element
 | ||||||
| 		if err := elemdec(s, val.Index(i)); err == EOL { | 		if err := elemdec(s, val.Index(i)); err == EOL { | ||||||
| 			break | 			break | ||||||
| 		} else if err != nil { | 		} else if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		i++ |  | ||||||
| 	} | 	} | ||||||
| 	if i < val.Len() { | 	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() | 	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 { | func decodeByteSlice(s *Stream, val reflect.Value) error { | ||||||
| 	kind, _, err := s.Kind() | 	kind, _, err := s.Kind() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if kind == List { | 	if kind == List { | ||||||
| 		return decodeList(s, val, decodeUint, maxInt) | 		return decodeListSlice(s, val, decodeUint) | ||||||
| 	} | 	} | ||||||
| 	b, err := s.Bytes() | 	b, err := s.Bytes() | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| @ -276,14 +288,15 @@ func decodeByteArray(s *Stream, val reflect.Value) error { | |||||||
| 		} | 		} | ||||||
| 		zero(val, int(size)) | 		zero(val, int(size)) | ||||||
| 	case List: | 	case List: | ||||||
| 		return decodeList(s, val, decodeUint, val.Len()) | 		return decodeListArray(s, val, decodeUint) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func zero(val reflect.Value, start int) { | func zero(val reflect.Value, start int) { | ||||||
| 	z := reflect.Zero(val.Type().Elem()) | 	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) | 		val.Index(i).Set(z) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -358,7 +371,7 @@ func decodeInterface(s *Stream, val reflect.Value) error { | |||||||
| 	} | 	} | ||||||
| 	if kind == List { | 	if kind == List { | ||||||
| 		slice := reflect.New(ifsliceType).Elem() | 		slice := reflect.New(ifsliceType).Elem() | ||||||
| 		if err := decodeList(s, slice, decodeInterface, maxInt); err != nil { | 		if err := decodeListSlice(s, slice, decodeInterface); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		val.Set(slice) | 		val.Set(slice) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user