Skip to content

Commit

Permalink
prevent overflow by blocking huge input at handler & querier
Browse files Browse the repository at this point in the history
  • Loading branch information
Yun committed Nov 24, 2019
1 parent 6bc6f38 commit d8455fe
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 17 deletions.
27 changes: 14 additions & 13 deletions x/market/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import (
)

const (
DefaultCodespace = types.DefaultCodespace
CodeInsufficientSwap = types.CodeInsufficientSwap
CodeNoEffectivePrice = types.CodeNoEffectivePrice
CodeRecursiveSwap = types.CodeRecursiveSwap
CodeInactive = types.CodeInactive
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
QuerySwap = types.QuerySwap
QueryTerraPoolDelta = types.QueryTerraPoolDelta
QueryParameters = types.QueryParameters
DefaultCodespace = types.DefaultCodespace
CodeInsufficientSwap = types.CodeInsufficientSwap
CodeNoEffectivePrice = types.CodeNoEffectivePrice
CodeRecursiveSwap = types.CodeRecursiveSwap
CodeInvalidOfferAmount = types.CodeInvalidOfferAmount
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
QuerySwap = types.QuerySwap
QueryTerraPoolDelta = types.QueryTerraPoolDelta
QueryParameters = types.QueryParameters
)

var (
Expand All @@ -32,6 +32,7 @@ var (
ErrNoEffectivePrice = types.ErrNoEffectivePrice
ErrInsufficientSwapCoins = types.ErrInsufficientSwapCoins
ErrRecursiveSwap = types.ErrRecursiveSwap
ErrInvalidOfferAmount = types.ErrInvalidOfferAmount
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
Expand Down
5 changes: 5 additions & 0 deletions x/market/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func handleMsgSwap(ctx sdk.Context, k Keeper, ms MsgSwap) sdk.Result {
return ErrRecursiveSwap(DefaultCodespace, ms.AskDenom).Result()
}

// Check overflow
if ms.OfferCoin.Amount.BigInt().BitLen() > 100 {
return ErrInvalidOfferAmount(DefaultCodespace, ms.OfferCoin).Result()
}

// Compute exchange rates between the ask and offer
swapCoin, spread, swapErr := k.ComputeSwap(ctx, ms.OfferCoin, ms.AskDenom)
if swapErr != nil {
Expand Down
11 changes: 11 additions & 0 deletions x/market/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,14 @@ func TestSwapMsg(t *testing.T) {
res = h(input.Ctx, swapMsg)
require.False(t, res.IsOK())
}

func TestSwapOverflowMsg(t *testing.T) {
input, h := setup(t)

amt, _ := sdk.NewIntFromString("10000000000000000000000000000000000000")
offerCoin := sdk.NewCoin(core.MicroLunaDenom, amt)
swapMsg := NewMsgSwap(keeper.Addrs[0], offerCoin, core.MicroSDRDenom)
res := h(input.Ctx, swapMsg)
require.False(t, res.IsOK())
require.Equal(t, CodeInvalidOfferAmount, res.Code)
}
4 changes: 4 additions & 0 deletions x/market/internal/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func querySwap(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, s
return nil, types.ErrRecursiveSwap(types.DefaultCodespace, params.AskDenom)
}

if params.OfferCoin.Amount.BigInt().BitLen() > 100 {
return nil, types.ErrInvalidOfferAmount(keeper.Codespace(), params.OfferCoin)
}

swapCoin, spread, err := keeper.ComputeSwap(ctx, params.OfferCoin, params.AskDenom)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("Failed to get swapped coin amount", err.Error()))
Expand Down
15 changes: 15 additions & 0 deletions x/market/internal/keeper/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ func TestQuerySwap(t *testing.T) {
res, err := querier(input.Ctx, []string{types.QuerySwap}, query)
require.Error(t, err)

// overflow query
overflowAmt, _ := sdk.NewIntFromString("1000000000000000000000000000000000")
overflowOfferCoin := sdk.NewCoin(core.MicroLunaDenom, overflowAmt)
queryParams = types.NewQuerySwapParams(overflowOfferCoin, core.MicroSDRDenom)
bz, err = cdc.MarshalJSON(queryParams)
require.NoError(t, err)

query = abci.RequestQuery{
Path: "",
Data: bz,
}

_, err = querier(input.Ctx, []string{types.QuerySwap}, query)
require.Error(t, err)

// valid query
queryParams = types.NewQuerySwapParams(offerCoin, core.MicroSDRDenom)
bz, err = cdc.MarshalJSON(queryParams)
Expand Down
13 changes: 9 additions & 4 deletions x/market/internal/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ type codeType = sdk.CodeType
const (
DefaultCodespace sdk.CodespaceType = "market"

CodeInsufficientSwap codeType = 1
CodeNoEffectivePrice codeType = 2
CodeRecursiveSwap codeType = 3
CodeInactive codeType = 4
CodeInsufficientSwap codeType = 1
CodeNoEffectivePrice codeType = 2
CodeRecursiveSwap codeType = 3
CodeInvalidOfferAmount codeType = 4
)

// ----------------------------------------
Expand All @@ -33,3 +33,8 @@ func ErrInsufficientSwapCoins(codespace sdk.CodespaceType, rval sdk.Int) sdk.Err
func ErrRecursiveSwap(codespace sdk.CodespaceType, denom string) sdk.Error {
return sdk.NewError(codespace, CodeRecursiveSwap, "Can't swap tokens with the same denomination: "+denom)
}

// ErrInvalidOfferAmount called when Offer coin amount is too huge
func ErrInvalidOfferAmount(codespace sdk.CodespaceType, coin sdk.Coin) sdk.Error {
return sdk.NewError(codespace, CodeInvalidOfferAmount, "Too hug offer coin amount: "+coin.String())
}
5 changes: 5 additions & 0 deletions x/oracle/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ func handleMsgExchangeRateVote(ctx sdk.Context, keeper Keeper, pvm MsgExchangeRa
return ErrVerificationFailed(keeper.Codespace(), bz, bz2).Result()
}

// Check overflow bit length
if pvm.ExchangeRate.BitLen() > 100+sdk.DecimalPrecisionBits {
return ErrInvalidExchangeRate(keeper.Codespace(), pvm.ExchangeRate).Result()
}

// Add the vote to the store
vote := NewExchangeRateVote(pvm.ExchangeRate, prevote.Denom, prevote.Voter)
keeper.DeleteExchangeRatePrevote(ctx, prevote)
Expand Down
18 changes: 18 additions & 0 deletions x/oracle/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ import (
"github.com/terra-project/core/x/oracle/internal/keeper"
)

func TestExchangeRateOverflow(t *testing.T) {
input, h := setup(t)

salt := "1"
overflowExchangeRate, _ := sdk.NewDecFromStr("100000000000000000000000000000000000000000000000000000000")

bz, err := VoteHash(salt, overflowExchangeRate, core.MicroSDRDenom, keeper.ValAddrs[0])
require.Nil(t, err)
prevoteMsg := NewMsgExchangeRatePrevote(hex.EncodeToString(bz), core.MicroSDRDenom, keeper.Addrs[0], keeper.ValAddrs[0])
res := h(input.Ctx, prevoteMsg)
require.True(t, res.IsOK())

voteMsg := NewMsgExchangeRateVote(overflowExchangeRate, salt, core.MicroSDRDenom, keeper.Addrs[0], keeper.ValAddrs[0])
res = h(input.Ctx.WithBlockHeight(1), voteMsg)
require.False(t, res.IsOK())
require.Equal(t, CodeInvalidExchangeRate, res.Code)
}

func TestOracleFilters(t *testing.T) {
input, h := setup(t)

Expand Down

0 comments on commit d8455fe

Please sign in to comment.