Skip to content

Commit 47f7a32

Browse files
committed
accounts/abi: Check for len%32==0 when unpacking methods, not events.
1 parent 3654aea commit 47f7a32

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

accounts/abi/abi.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,17 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
7474

7575
// Unpack output in v according to the abi specification
7676
func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) {
77-
if err = bytesAreProper(output); err != nil {
78-
return err
77+
if len(output) == 0 {
78+
return fmt.Errorf("abi: unmarshalling empty output")
7979
}
80+
8081
// since there can't be naming collisions with contracts and events,
8182
// we need to decide whether we're calling a method or an event
8283
var unpack unpacker
8384
if method, ok := abi.Methods[name]; ok {
85+
if len(output)%32 != 0 {
86+
return fmt.Errorf("abi: improperly formatted output")
87+
}
8488
unpack = method
8589
} else if event, ok := abi.Events[name]; ok {
8690
unpack = event

accounts/abi/abi_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package abi
1818

1919
import (
2020
"bytes"
21+
"encoding/hex"
2122
"fmt"
2223
"log"
2324
"math/big"
@@ -418,3 +419,43 @@ func TestBareEvents(t *testing.T) {
418419
}
419420
}
420421
}
422+
423+
// TestUnpackEvent is based on this contract:
424+
// contract T {
425+
// event received(address sender, uint amount, bytes memo);
426+
// function receive(bytes memo) external payable {
427+
// received(msg.sender, msg.value, memo);
428+
// }
429+
// }
430+
// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
431+
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
432+
func TestUnpackEvent(t *testing.T) {
433+
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]`
434+
abi, err := JSON(strings.NewReader(abiJSON))
435+
if err != nil {
436+
t.Fatal(err)
437+
}
438+
439+
const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
440+
data, err := hex.DecodeString(hexdata)
441+
if err != nil {
442+
t.Fatal(err)
443+
}
444+
if len(data)%32 == 0 {
445+
t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
446+
}
447+
448+
type ReceivedEvent struct {
449+
Address common.Address
450+
Amount *big.Int
451+
Memo []byte
452+
}
453+
var ev ReceivedEvent
454+
455+
err = abi.Unpack(&ev, "received", data)
456+
if err != nil {
457+
t.Error(err)
458+
} else {
459+
t.Logf("len(data): %d; received event: %+v", len(data), ev)
460+
}
461+
}

accounts/abi/unpack.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,3 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err
203203
//fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start)
204204
return
205205
}
206-
207-
// checks for proper formatting of byte output
208-
func bytesAreProper(output []byte) error {
209-
if len(output) == 0 {
210-
return fmt.Errorf("abi: unmarshalling empty output")
211-
} else if len(output)%32 != 0 {
212-
return fmt.Errorf("abi: improperly formatted output")
213-
} else {
214-
return nil
215-
}
216-
}

0 commit comments

Comments
 (0)