From c4bf02a5b5893f35503bc6bfd652c3aedc5b5cc0 Mon Sep 17 00:00:00 2001 From: protolambda Date: Sat, 30 Dec 2017 17:22:58 +0100 Subject: [PATCH] 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. --- accounts/abi/unpack.go | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index 33b5b994c5..ac56435d55 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -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 func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) { 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") } - 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) if err != nil { 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 - refSlice.Index(j).Set(reflectedInter) + refSlice.Index(j).Set(reflect.ValueOf(inter)) } // return the interface