mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
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:
parent
2444b61cf3
commit
4ed1e0262e
1 changed files with 14 additions and 7 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue