mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
rlp: propagate struct field type errors
If a struct contained fields of undecodable type, the encoder and
decoder would panic instead of returning an error. Fix this by
propagating type errors in makeStruct{Writer,Decoder} and add a test.
This commit is contained in:
parent
ea2e659fc3
commit
2d98862cd7
5 changed files with 32 additions and 2 deletions
|
|
@ -385,6 +385,11 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for _, f := range fields {
|
||||||
|
if f.info.decoderErr != nil {
|
||||||
|
return nil, structFieldError{typ, f.index, f.info.decoderErr}
|
||||||
|
}
|
||||||
|
}
|
||||||
dec := func(s *Stream, val reflect.Value) (err error) {
|
dec := func(s *Stream, val reflect.Value) (err error) {
|
||||||
if _, err := s.List(); err != nil {
|
if _, err := s.List(); err != nil {
|
||||||
return wrapStreamError(err, typ)
|
return wrapStreamError(err, typ)
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,10 @@ type nilStringSlice struct {
|
||||||
X *[]uint `rlp:"nilString"`
|
X *[]uint `rlp:"nilString"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type intField struct {
|
||||||
|
X int
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
veryBigInt = big.NewInt(0).Add(
|
veryBigInt = big.NewInt(0).Add(
|
||||||
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
||||||
|
|
@ -496,6 +500,11 @@ var decodeTests = []decodeTest{
|
||||||
ptr: new(recstruct),
|
ptr: new(recstruct),
|
||||||
error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
|
error: "rlp: expected input string or byte for uint, decoding into (rlp.recstruct).Child.I",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "C103",
|
||||||
|
ptr: new(intField),
|
||||||
|
error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
input: "C50102C20102",
|
input: "C50102C20102",
|
||||||
ptr: new(tailUint),
|
ptr: new(tailUint),
|
||||||
|
|
@ -531,12 +540,12 @@ var decodeTests = []decodeTest{
|
||||||
{
|
{
|
||||||
input: "C0",
|
input: "C0",
|
||||||
ptr: new(invalidTail1),
|
ptr: new(invalidTail1),
|
||||||
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail1.A (must be on last field)",
|
error: `rlp: invalid struct tag "tail" for rlp.invalidTail1.A (must be on last field)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "C0",
|
input: "C0",
|
||||||
ptr: new(invalidTail2),
|
ptr: new(invalidTail2),
|
||||||
error: "rlp: invalid struct tag \"tail\" for rlp.invalidTail2.B (field type is not slice)",
|
error: `rlp: invalid struct tag "tail" for rlp.invalidTail2.B (field type is not slice)`,
|
||||||
},
|
},
|
||||||
|
|
||||||
// struct tag "-"
|
// struct tag "-"
|
||||||
|
|
|
||||||
|
|
@ -480,6 +480,11 @@ func makeStructWriter(typ reflect.Type) (writer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for _, f := range fields {
|
||||||
|
if f.info.writerErr != nil {
|
||||||
|
return nil, structFieldError{typ, f.index, f.info.writerErr}
|
||||||
|
}
|
||||||
|
}
|
||||||
writer := func(val reflect.Value, w *encbuf) error {
|
writer := func(val reflect.Value, w *encbuf) error {
|
||||||
lh := w.list()
|
lh := w.list()
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ var encTests = []encTest{
|
||||||
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
||||||
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
||||||
{val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"},
|
{val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"},
|
||||||
|
{val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"},
|
||||||
|
|
||||||
// nil
|
// nil
|
||||||
{val: (*uint)(nil), output: "80"},
|
{val: (*uint)(nil), output: "80"},
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,16 @@ func structFields(typ reflect.Type) (fields []field, err error) {
|
||||||
return fields, nil
|
return fields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type structFieldError struct {
|
||||||
|
typ reflect.Type
|
||||||
|
field int
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e structFieldError) Error() string {
|
||||||
|
return fmt.Sprintf("%v (struct field %v.%s)", e.err, e.typ, e.typ.Field(e.field).Name)
|
||||||
|
}
|
||||||
|
|
||||||
type structTagError struct {
|
type structTagError struct {
|
||||||
typ reflect.Type
|
typ reflect.Type
|
||||||
field, tag, err string
|
field, tag, err string
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue