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 {
|
||||
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) {
|
||||
if _, err := s.List(); err != nil {
|
||||
return wrapStreamError(err, typ)
|
||||
|
|
|
|||
|
|
@ -365,6 +365,10 @@ type nilStringSlice struct {
|
|||
X *[]uint `rlp:"nilString"`
|
||||
}
|
||||
|
||||
type intField struct {
|
||||
X int
|
||||
}
|
||||
|
||||
var (
|
||||
veryBigInt = big.NewInt(0).Add(
|
||||
big.NewInt(0).Lsh(big.NewInt(0xFFFFFFFFFFFFFF), 16),
|
||||
|
|
@ -496,6 +500,11 @@ var decodeTests = []decodeTest{
|
|||
ptr: new(recstruct),
|
||||
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",
|
||||
ptr: new(tailUint),
|
||||
|
|
@ -531,12 +540,12 @@ var decodeTests = []decodeTest{
|
|||
{
|
||||
input: "C0",
|
||||
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",
|
||||
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 "-"
|
||||
|
|
|
|||
|
|
@ -480,6 +480,11 @@ func makeStructWriter(typ reflect.Type) (writer, error) {
|
|||
if err != nil {
|
||||
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 {
|
||||
lh := w.list()
|
||||
for _, f := range fields {
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ var encTests = []encTest{
|
|||
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
||||
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
||||
{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
|
||||
{val: (*uint)(nil), output: "80"},
|
||||
|
|
|
|||
|
|
@ -126,6 +126,16 @@ func structFields(typ reflect.Type) (fields []field, err error) {
|
|||
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 {
|
||||
typ reflect.Type
|
||||
field, tag, err string
|
||||
|
|
|
|||
Loading…
Reference in a new issue