Skip to content

Commit 6a4d025

Browse files
authored
Bug decode abi bytes (#235)
* Add test * Fix abi decode dynamic length items * Add Decode panic test
1 parent 7658a30 commit 6a4d025

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

abi/abi_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,49 +247,49 @@ func TestAbi_HumanReadable(t *testing.T) {
247247
Inputs: MustNewType("tuple(string symbol, string name)"),
248248
},
249249
Methods: map[string]*Method{
250-
"transferFrom": &Method{
250+
"transferFrom": {
251251
Name: "transferFrom",
252252
Inputs: MustNewType("tuple(address from, address to, uint256 value)"),
253253
Outputs: MustNewType("tuple()"),
254254
},
255-
"balanceOf": &Method{
255+
"balanceOf": {
256256
Name: "balanceOf",
257257
Inputs: MustNewType("tuple(address owner)"),
258258
Outputs: MustNewType("tuple(uint256 balance)"),
259259
},
260-
"balanceOf0": &Method{
260+
"balanceOf0": {
261261
Name: "balanceOf",
262262
Inputs: MustNewType("tuple()"),
263263
Outputs: MustNewType("tuple()"),
264264
},
265-
"addPerson": &Method{
265+
"addPerson": {
266266
Name: "addPerson",
267267
Inputs: MustNewType("tuple(tuple(string name, uint16 age) person)"),
268268
Outputs: MustNewType("tuple()"),
269269
},
270-
"addPeople": &Method{
270+
"addPeople": {
271271
Name: "addPeople",
272272
Inputs: MustNewType("tuple(tuple(string name, uint16 age)[] person)"),
273273
Outputs: MustNewType("tuple()"),
274274
},
275-
"getPerson": &Method{
275+
"getPerson": {
276276
Name: "getPerson",
277277
Inputs: MustNewType("tuple(uint256 id)"),
278278
Outputs: MustNewType("tuple(tuple(string name, uint16 age))"),
279279
},
280280
},
281281
Events: map[string]*Event{
282-
"Transfer": &Event{
282+
"Transfer": {
283283
Name: "Transfer",
284284
Inputs: MustNewType("tuple(address indexed from, address indexed to, address value)"),
285285
},
286-
"PersonAdded": &Event{
286+
"PersonAdded": {
287287
Name: "PersonAdded",
288288
Inputs: MustNewType("tuple(uint256 indexed id, tuple(string name, uint16 age) person)"),
289289
},
290290
},
291291
Errors: map[string]*Error{
292-
"InsufficientBalance": &Error{
292+
"InsufficientBalance": {
293293
Name: "InsufficientBalance",
294294
Inputs: MustNewType("tuple(address owner, uint256 balance)"),
295295
},

abi/decode.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,10 @@ func readLength(data []byte) (int, error) {
296296
return 0, fmt.Errorf("length larger than int64: %v", lengthBig.Int64())
297297
}
298298
length := int(lengthBig.Uint64())
299-
if length > len(data) {
299+
300+
// if we trim the length in the data there should be enough
301+
// bytes to cover the length
302+
if length > len(data)-32 {
300303
return 0, fmt.Errorf("length insufficient %v require %v", len(data), length)
301304
}
302305
return length, nil

abi/decode_test.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
package abi
22

3-
import "testing"
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
48

59
func TestDecode_BytesBound(t *testing.T) {
610
typ := MustNewType("tuple(string)")
711
decodeTuple(typ, nil) // it should not panic
812
}
13+
14+
func TestDecode_DynamicLengthOutOfBounds(t *testing.T) {
15+
input := []byte("00000000000000000000000000000000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00000000000000000000000000")
16+
typ := MustNewType("tuple(bytes32, bytes, bytes)")
17+
18+
_, err := Decode(typ, input)
19+
require.Error(t, err)
20+
}

abi/encoding_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,35 @@ func TestRandomEncoding(t *testing.T) {
621621
if err := testEncodeDecode(t, server, tt, input); err != nil {
622622
t.Fatal(err)
623623
}
624+
625+
if err := testDecodePanic(tt, input); err != nil {
626+
t.Fatal(err)
627+
}
624628
})
625629
}
626630
}
627631

632+
func testDecodePanic(tt *Type, input interface{}) error {
633+
// test that the encoded input and random permutattions of the response do not cause
634+
// panics on Decode function
635+
res1, err := Encode(input, tt)
636+
if err != nil {
637+
return err
638+
}
639+
640+
buf := make([]byte, len(res1))
641+
642+
// change each bit of the input with 1
643+
for i := 0; i < len(res1); i++ {
644+
copy(buf, res1)
645+
buf[i] = 0xff
646+
647+
Decode(tt, buf)
648+
}
649+
650+
return nil
651+
}
652+
628653
func testTypeWithContract(t *testing.T, server *testutil.TestServer, typ *Type) error {
629654
g := &generateContractImpl{}
630655
source := g.run(typ)

0 commit comments

Comments
 (0)