mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
accounts/abi: Fix unpacking of nested arrays
Removed the temporary workaround of packing to calculate size, which was incorrect for slice-like types anyway. Full size of nested arrays is used now.
This commit is contained in:
parent
f428ef3e5d
commit
0e69ad846e
1 changed files with 19 additions and 13 deletions
|
|
@ -93,6 +93,17 @@ func readFixedBytes(t Type, word []byte) (interface{}, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDeepSizeForType(t *Type) int {
|
||||||
|
//all other should be counted as 32 (slices have pointers to respective elements)
|
||||||
|
size := 32
|
||||||
|
//arrays wrap it, each element being the same size
|
||||||
|
for t.T == ArrayTy {
|
||||||
|
size *= t.Size
|
||||||
|
t = t.Elem
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
// iteratively unpack elements
|
// iteratively unpack elements
|
||||||
func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
|
func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
|
|
@ -115,25 +126,20 @@ 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 < size; j++ {
|
elemSize := 32
|
||||||
|
if t.T == ArrayTy {
|
||||||
|
elemSize = getDeepSizeForType(t.Elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, j := start, 0; j < size; i, j = i+elemSize, j+1 {
|
||||||
|
|
||||||
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(reflectedInter)
|
refSlice.Index(j).Set(reflect.ValueOf(inter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the interface
|
// return the interface
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue