evm: check height overflow (#597)

* evm: check height overflow

* rm

* c++
This commit is contained in:
Federico Kunze Küllmer 2021-09-28 11:48:11 +02:00 committed by GitHub
parent bc82f3f8eb
commit 83627b9967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 1 deletions

View File

@ -56,6 +56,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes
* (evm) [tharsis#597](https://github.com/tharsis/ethermint/pull/597) Check for `uint64` -> `int64` block height overflow on `GetHashFn`
* (evm) [tharsis#579](https://github.com/tharsis/ethermint/pull/579) Update `DeriveChainID` function to handle `v` signature values `< 35`.
* (encoding) [tharsis#478](https://github.com/tharsis/ethermint/pull/478) Register `Evidence` to amino codec.
* (rpc) [tharsis#478](https://github.com/tharsis/ethermint/pull/481) Getting the node configuration when calling the `miner` rpc methods.

View File

@ -2,6 +2,7 @@ package types
import (
"bytes"
"math"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
@ -27,3 +28,12 @@ func ValidateAddress(address string) error {
}
return nil
}
// SafeInt64 checks for overflows while casting a uint64 to int64 value.
func SafeInt64(value uint64) (int64, error) {
if value > uint64(math.MaxInt64) {
return 0, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "uint64 value %v cannot exceed %v", value, int64(math.MaxInt64))
}
return int64(value), nil
}

View File

@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"github.com/tharsis/ethermint/tests"
)
func TestIsEmptyHash(t *testing.T) {
@ -52,3 +53,60 @@ func TestIsZeroAddress(t *testing.T) {
require.Equal(t, tc.expEmpty, IsZeroAddress(tc.address), tc.name)
}
}
func TestValidateAddress(t *testing.T) {
testCases := []struct {
name string
address string
expError bool
}{
{
"empty string", "", true,
},
{
"invalid address", "0x", true,
},
{
"zero address", common.Address{}.String(), false,
},
{
"valid address", tests.GenerateAddress().Hex(), false,
},
}
for _, tc := range testCases {
err := ValidateAddress(tc.address)
if tc.expError {
require.Error(t, err, tc.name)
} else {
require.NoError(t, err, tc.name)
}
}
}
func TestSafeInt64(t *testing.T) {
testCases := []struct {
name string
value uint64
expError bool
}{
{
"no overflow", 10, false,
},
{
"overflow", 18446744073709551615, true,
},
}
for _, tc := range testCases {
value, err := SafeInt64(tc.value)
if tc.expError {
require.Error(t, err, tc.name)
continue
}
require.NoError(t, err, tc.name)
require.Equal(t, int64(tc.value), value, tc.name)
}
}

View File

@ -66,8 +66,14 @@ func (k Keeper) VMConfig(msg core.Message, params types.Params, tracer vm.Tracer
// 3. The requested height is from a height greater than the latest one
func (k Keeper) GetHashFn() vm.GetHashFunc {
return func(height uint64) common.Hash {
h := int64(height)
ctx := k.Ctx()
h, err := ethermint.SafeInt64(height)
if err != nil {
k.Logger(ctx).Error("failed to cast height to int64", "error", err)
return common.Hash{}
}
switch {
case ctx.BlockHeight() == h:
// Case 1: The requested height matches the one from the context so we can retrieve the header