accounts/abi: bugfix for unpacking nested arrays

The code previously assumed the arrays/slices were always 1 level
deep. While the packing supports nested arrays (!!!).

The current code for unpacking doesn't return the "consumed" length, so
this fix had to work around that by calculating it (i.e. packing and
 getting resulting length) after the unpacking of the array element.
It's far from ideal, but unpacking behaviour is fixed now.
This commit is contained in:
protolambda 2017-12-29 00:34:33 +01:00
parent 2444b61cf3
commit 4ed1e0262e
No known key found for this signature in database
GPG key ID: EC89FDBB2B4C7623

View file

@ -104,7 +104,6 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
// this value will become our slice or our array, depending on the type // this value will become our slice or our array, depending on the type
var refSlice reflect.Value var refSlice reflect.Value
slice := output[start : start+size*32]
if t.T == SliceTy { if t.T == SliceTy {
// declare our slice // declare our slice
@ -116,17 +115,25 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage") return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage")
} }
for i, j := start, 0; j*32 < len(slice); i, j = i+32, j+1 { for i, j := start, 0; j < size; j++ {
// this corrects the arrangement so that we get all the underlying array values
if t.Elem.T == ArrayTy && j != 0 {
i = start + t.Elem.Size*32*j
}
inter, err := toGoType(i, *t.Elem, output) inter, err := toGoType(i, *t.Elem, output)
if err != nil { if err != nil {
return nil, err return nil, err
} }
reflectedInter := reflect.ValueOf(inter)
//Although we just did the reverse, pack it, to get the length of the actual element.
//Getting the length directly from the "toGoType" would be way better,
// but it requires some refactoring to get it return the *consumed* length.
interPacked, err := t.Elem.pack(reflectedInter)
if err != nil {
return nil, err
}
i += len(interPacked)
// append the item to our reflect slice // append the item to our reflect slice
refSlice.Index(j).Set(reflect.ValueOf(inter)) refSlice.Index(j).Set(reflectedInter)
} }
// return the interface // return the interface