aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-01-16 06:21:41 +0800
committerFelix Lange <fjl@twurst.com>2015-01-16 06:35:26 +0800
commitfc92abec2cc6e27e7e56a6a05850ad4ebbf63d7e (patch)
treef8ba38e7c5ad3be52fc22c09600b619e1f968c53
parent29c46cdf3405d6462deb2cb5cef87b1b4fb2bdc7 (diff)
downloadgo-tangerine-fc92abec2cc6e27e7e56a6a05850ad4ebbf63d7e.tar.gz
go-tangerine-fc92abec2cc6e27e7e56a6a05850ad4ebbf63d7e.tar.zst
go-tangerine-fc92abec2cc6e27e7e56a6a05850ad4ebbf63d7e.zip
rlp: allow encoding non-empty interface values
This needs to be supported because []someInterface does occur sometimes. Funny enough, the fix involves changes to the decoder. makeDecoder cannot return an error for non-empty interfaces anymore because the type cache builds both decoder and writer. Do the check at 'runtime' instead.
-rw-r--r--rlp/decode.go5
-rw-r--r--rlp/decode_test.go5
-rw-r--r--rlp/encode.go3
-rw-r--r--rlp/encode_test.go13
4 files changed, 23 insertions, 3 deletions
diff --git a/rlp/decode.go b/rlp/decode.go
index 972e662c2..55f7187a3 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -137,7 +137,7 @@ func makeDecoder(typ reflect.Type) (dec decoder, err error) {
return makeStructDecoder(typ)
case kind == reflect.Ptr:
return makePtrDecoder(typ)
- case kind == reflect.Interface && typ.NumMethod() == 0:
+ case kind == reflect.Interface:
return decodeInterface, nil
default:
return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ)
@@ -378,6 +378,9 @@ func makePtrDecoder(typ reflect.Type) (decoder, error) {
var ifsliceType = reflect.TypeOf([]interface{}{})
func decodeInterface(s *Stream, val reflect.Value) error {
+ if val.Type().NumMethod() != 0 {
+ return fmt.Errorf("rlp: type %v is not RLP-serializable", val.Type())
+ }
kind, _, err := s.Kind()
if err != nil {
return err
diff --git a/rlp/decode_test.go b/rlp/decode_test.go
index 9142ef56d..9f66840b1 100644
--- a/rlp/decode_test.go
+++ b/rlp/decode_test.go
@@ -325,6 +325,11 @@ var decodeTests = []decodeTest{
{input: "850505050505", ptr: new(interface{}), value: []byte{5, 5, 5, 5, 5}},
{input: "C0", ptr: new(interface{}), value: []interface{}{}},
{input: "C50183040404", ptr: new(interface{}), value: []interface{}{[]byte{1}, []byte{4, 4, 4}}},
+ {
+ input: "C3010203",
+ ptr: new([]io.Reader),
+ error: "rlp: type io.Reader is not RLP-serializable",
+ },
}
func uintp(i uint) *uint { return &i }
diff --git a/rlp/encode.go b/rlp/encode.go
index 689d25dd8..d80b66315 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -280,7 +280,6 @@ func (r *encReader) next() []byte {
var (
encoderInterface = reflect.TypeOf(new(Encoder)).Elem()
- emptyInterface = reflect.TypeOf(new(interface{})).Elem()
big0 = big.NewInt(0)
)
@@ -292,7 +291,7 @@ func makeWriter(typ reflect.Type) (writer, error) {
return writeEncoder, nil
case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface):
return writeEncoderNoPtr, nil
- case typ == emptyInterface:
+ case kind == reflect.Interface:
return writeInterface, nil
case typ.AssignableTo(reflect.PtrTo(bigInt)):
return writeBigIntPtr, nil
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index 8dba3671b..18b843737 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -32,9 +32,19 @@ func (e byteEncoder) EncodeRLP(w io.Writer) error {
return nil
}
+type encodableReader struct {
+ A, B uint
+}
+
+func (e *encodableReader) Read(b []byte) (int, error) {
+ panic("called")
+}
+
var (
_ = Encoder(&testEncoder{})
_ = Encoder(byteEncoder(0))
+
+ reader io.Reader = &encodableReader{1, 2}
)
type encTest struct {
@@ -176,6 +186,9 @@ var encTests = []encTest{
{val: (*[]struct{ uint })(nil), output: "C0"},
{val: (*interface{})(nil), output: "C0"},
+ // interfaces
+ {val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
+
// Encoder
{val: (*testEncoder)(nil), output: "00000000"},
{val: &testEncoder{}, output: "00010001000100010001"},