diff --git a/execution/evm/abi/abi.go b/execution/evm/abi/abi.go index 99cc07c31fa1482fdaf5ec9ce65a1f4f8e0d932e..bced18f48b6661593e16c09a0ed163d287fccdd3 100644 --- a/execution/evm/abi/abi.go +++ b/execution/evm/abi/abi.go @@ -404,8 +404,8 @@ func (e EVMInt) unpack(data []byte, offset int, v interface{}) (int, error) { if sign { return 0, fmt.Errorf("cannot convert negative EVM int to %s", toType) } - maxLen := int(unsafe.Sizeof(new(uint64))) - if length > maxLen || (data[ElementSize-maxLen]&0x80) != 0 { + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen { return 0, fmt.Errorf("value to large for uint64") } *v = binary.BigEndian.Uint64(data[ElementSize-maxLen : ElementSize]) @@ -413,35 +413,35 @@ func (e EVMInt) unpack(data []byte, offset int, v interface{}) (int, error) { if sign { return 0, fmt.Errorf("cannot convert negative EVM int to %s", toType) } - maxLen := int(unsafe.Sizeof(new(uint32))) - if length > maxLen || (data[ElementSize-maxLen]&0x80) != 0 { - return 0, fmt.Errorf("value to large for uint64") + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen { + return 0, fmt.Errorf("value to large for int32") } *v = binary.BigEndian.Uint32(data[ElementSize-maxLen : ElementSize]) case *uint16: if sign { return 0, fmt.Errorf("cannot convert negative EVM int to %s", toType) } - maxLen := int(unsafe.Sizeof(new(uint16))) - if length > maxLen || (data[ElementSize-maxLen]&0x80) != 0 { + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen { return 0, fmt.Errorf("value to large for uint16") } *v = binary.BigEndian.Uint16(data[ElementSize-maxLen : ElementSize]) case *int64: - maxLen := int(unsafe.Sizeof(new(int64))) - if length > maxLen { - return 0, fmt.Errorf("value to large for uint64") + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen || (inv[ElementSize-maxLen]&0x80) != 0 { + return 0, fmt.Errorf("value to large for int64") } *v = int64(binary.BigEndian.Uint64(data[ElementSize-maxLen : ElementSize])) case *int32: - maxLen := int(unsafe.Sizeof(new(int32))) - if length > maxLen { + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen || (inv[ElementSize-maxLen]&0x80) != 0 { return 0, fmt.Errorf("value to large for uint64") } *v = int32(binary.BigEndian.Uint32(data[ElementSize-maxLen : ElementSize])) case *int16: - maxLen := int(unsafe.Sizeof(new(uint16))) - if length > maxLen { + maxLen := int(unsafe.Sizeof(*v)) + if length > maxLen || (inv[ElementSize-maxLen]&0x80) != 0 { return 0, fmt.Errorf("value to large for uint16") } *v = int16(binary.BigEndian.Uint16(data[ElementSize-maxLen : ElementSize])) diff --git a/execution/evm/abi/core_test.go b/execution/evm/abi/core_test.go index b21772f1526cafa8af06dec9cee660985e73f710..b4b987762a01820f41568ec33c26b49a25736e29 100644 --- a/execution/evm/abi/core_test.go +++ b/execution/evm/abi/core_test.go @@ -3,9 +3,11 @@ package abi import ( "bytes" "fmt" + "math/big" "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tmthrgd/go-hex" ) @@ -138,7 +140,7 @@ func TestPacker(t *testing.T) { } } -func TestUnpacker(t *testing.T) { +func TestUnpackerString(t *testing.T) { for _, test := range []struct { abi string packed []byte @@ -326,6 +328,108 @@ func TestUnpacker(t *testing.T) { } } +func TestUnpacker(t *testing.T) { + for _, test := range []struct { + evm EVMType + packed []byte + data interface{} + expectedOutput interface{} + }{ + /* positive numbers */ + { + EVMInt{M: 256}, + pad([]byte{42}, 32, true), + new(int64), + func() *int64 { var v int64; v = 42; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{42}, 32, true), + new(int32), + func() *int32 { var v int32; v = 42; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{0x7f, 0xff}, 32, true), + new(int16), + func() *int16 { var v int16; v = 0x7fff; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{0xfd, 0xca}, 32, true), + new(uint16), + func() *uint16 { var v uint16; v = 0xfdca; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{0xfd, 0xca}, 32, true), + new(uint32), + func() *uint32 { var v uint32; v = 0xfdca; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{0xfd, 0xca, 0, 0, 0, 0, 0, 0}, 32, true), + new(uint64), + func() *uint64 { var v uint64; v = 0xfdca000000000000; return &v }(), + }, + { + EVMInt{M: 256}, + pad([]byte{42}, 32, true), + new(big.Int), + big.NewInt(42), + }, + /* Negative numbers */ + { + EVMInt{M: 256}, + hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6"), + new(int64), + func() *int64 { var v int64; v = -42; return &v }(), + }, + { + EVMInt{M: 256}, + hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6"), + new(int32), + func() *int32 { var v int32; v = -42; return &v }(), + }, + { + EVMInt{M: 256}, + hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8001"), + new(int16), + func() *int16 { var v int16; v = -0x7fff; return &v }(), + }, + { + EVMInt{M: 256}, + hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6C20"), + new(int32), + func() *int32 { var v int32; v = -300000; return &v }(), + }, + { + EVMInt{M: 256}, + hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35010124111"), + new(int64), + func() *int64 { var v int64; v = -0xcafefedbeef; return &v }(), + }, + { + EVMInt{M: 256}, + hexToBytes(t, "80000000000000000000000000000000000000000000000000000CAFEFEDBEEF"), + new(big.Int), + func() *big.Int { + v := new(big.Int) + x, _ := v.SetString("-57896044618658097711785492504343953926634992332820282019728791990006780674321", 10) + return x + }(), + }, + } { + //t.Log(test.name) + t.Log(test.packed) + _, err := test.evm.unpack(test.packed, 0, test.data) + if err != nil { + t.Errorf("Unpacker failed: %v", err) + } + assert.EqualValues(t, test.expectedOutput, test.data) + } +} + func hexToBytes(t testing.TB, hexString string) []byte { bs, err := hex.DecodeString(hexString) require.NoError(t, err)