Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ABI] Out-of-bound access fixed #1872

Merged
merged 4 commits into from Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 37 additions & 0 deletions accounts/abi/abi_test.go
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/klaytn/klaytn/common"
"github.com/klaytn/klaytn/common/math"
"github.com/klaytn/klaytn/crypto"
"github.com/stretchr/testify/assert"
)

const jsondata = `
Expand Down Expand Up @@ -763,6 +764,42 @@ func TestUnpackEvent(t *testing.T) {
}
}

// Testset (ABI and hexdata) was created based on this contract format.
/*
contract T {
event eventInDynamicType(uint elem1, string[3] elem2);
constructor() {}
function test123() public {
string[3] memory vals = ["A","B","C"];
emit eventInDynamicType(123, vals);
}
}
*/
func TestUnpackEventOffsetBound(t *testing.T) {
const abiJSON = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"elem1","type":"uint256"},{"indexed":false,"internalType":"string[3]","name":"elem2","type":"string[3]"}],"name":"ev123","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"elem1","type":"uint256"},{"indexed":false,"internalType":"string[3]","name":"elem2","type":"string[3]"}],"name":"eventInDynamicType","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"receivedAddr","type":"event"},{"inputs":[],"name":"test123","outputs":[],"stateMutability":"nonpayable","type":"function"}]`

abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
t.Fatal(err)
}

// Commented bytes are pure data. Offset value was modified to make a crash
// const hexdata = `000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000354242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242000000000000000000000000000000000000000000000000000000000000000000000000000000000000684343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343000000000000000000000000000000000000000000000000`
const hexdata = `000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000fff000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000354242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242000000000000000000000000000000000000000000000000000000000000000000000000000000000000684343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343000000000000000000000000000000000000000000000000`
blukat29 marked this conversation as resolved.
Show resolved Hide resolved
data, err := hex.DecodeString(hexdata)
if err != nil {
t.Fatal(err)
}

type evObj struct {
Myval *big.Int
Myvals [3]string
}

var params evObj
assert.NotNil(t, abi.Unpack(&params, "eventInDynamicType", data))
}

func TestUnpackEventIntoMap(t *testing.T) {
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"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
Expand Down
5 changes: 4 additions & 1 deletion accounts/abi/unpack.go
Expand Up @@ -227,7 +227,10 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) {
return forEachUnpack(t, output[begin:], 0, length)
case ArrayTy:
if isDynamicType(*t.Elem) {
offset := int64(binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:]))
offset := binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:])
if offset > uint64(len(output)) {
return nil, fmt.Errorf("abi: toGoType offset greater than output length: offset: %d, len(output): %d", offset, len(output))
}
return forEachUnpack(t, output[offset:], 0, t.Size)
}
return forEachUnpack(t, output[index:], 0, t.Size)
Expand Down