Skip to content

Commit

Permalink
Merge PR #3552: General Sanitization & Gas Cost Review
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored and cwgoes committed Feb 8, 2019
1 parent e7e3c32 commit fd5e7b9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
2 changes: 2 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ IMPROVEMENTS
* \#2509 Sanitize all usage of Dec.RoundInt64()
* [\#556](https://github.com/cosmos/cosmos-sdk/issues/556) Increase `BaseApp`
test coverage.
* [\#3552](https://github.com/cosmos/cosmos-sdk/pull/3552) Validate bit length when
deserializing `Int` types.

* Tendermint

Expand Down
36 changes: 26 additions & 10 deletions types/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package types

import (
"encoding/json"
"fmt"
"testing"

"math/big"
"math/rand"
)

const maxBitLen = 255

func newIntegerFromString(s string) (*big.Int, bool) {
return new(big.Int).SetString(s, 0)
}
Expand Down Expand Up @@ -58,9 +61,21 @@ func marshalAmino(i *big.Int) (string, error) {
return string(bz), err
}

func unmarshalText(i *big.Int, text string) error {
if err := i.UnmarshalText([]byte(text)); err != nil {
return err
}

if i.BitLen() > maxBitLen {
return fmt.Errorf("integer out of range: %s", text)
}

return nil
}

// UnmarshalAmino for custom decoding scheme
func unmarshalAmino(i *big.Int, text string) (err error) {
return i.UnmarshalText([]byte(text))
return unmarshalText(i, text)
}

// MarshalJSON for custom encoding scheme
Expand All @@ -81,12 +96,13 @@ func unmarshalJSON(i *big.Int, bz []byte) error {
if err != nil {
return err
}
return i.UnmarshalText([]byte(text))

return unmarshalText(i, text)
}

// Int wraps integer with 256 bit range bound
// Checks overflow, underflow and division by zero
// Exists in range from -(2^255-1) to 2^255-1
// Exists in range from -(2^maxBitLen-1) to 2^maxBitLen-1
type Int struct {
i *big.Int
}
Expand All @@ -103,7 +119,7 @@ func NewInt(n int64) Int {

// NewIntFromBigInt constructs Int from big.Int
func NewIntFromBigInt(i *big.Int) Int {
if i.BitLen() > 255 {
if i.BitLen() > maxBitLen {
panic("NewIntFromBigInt() out of bound")
}
return Int{i}
Expand All @@ -116,7 +132,7 @@ func NewIntFromString(s string) (res Int, ok bool) {
return
}
// Check overflow
if i.BitLen() > 255 {
if i.BitLen() > maxBitLen {
ok = false
return
}
Expand All @@ -134,7 +150,7 @@ func NewIntWithDecimal(n int64, dec int) Int {
i.Mul(big.NewInt(n), exp)

// Check overflow
if i.BitLen() > 255 {
if i.BitLen() > maxBitLen {
panic("NewIntWithDecimal() out of bound")
}
return Int{i}
Expand Down Expand Up @@ -210,7 +226,7 @@ func (i Int) LTE(i2 Int) bool {
func (i Int) Add(i2 Int) (res Int) {
res = Int{add(i.i, i2.i)}
// Check overflow
if res.i.BitLen() > 255 {
if res.i.BitLen() > maxBitLen {
panic("Int overflow")
}
return
Expand All @@ -225,7 +241,7 @@ func (i Int) AddRaw(i2 int64) Int {
func (i Int) Sub(i2 Int) (res Int) {
res = Int{sub(i.i, i2.i)}
// Check overflow
if res.i.BitLen() > 255 {
if res.i.BitLen() > maxBitLen {
panic("Int overflow")
}
return
Expand All @@ -239,12 +255,12 @@ func (i Int) SubRaw(i2 int64) Int {
// Mul multiples two Ints
func (i Int) Mul(i2 Int) (res Int) {
// Check overflow
if i.i.BitLen()+i2.i.BitLen()-1 > 255 {
if i.i.BitLen()+i2.i.BitLen()-1 > maxBitLen {
panic("Int overflow")
}
res = Int{mul(i.i, i2.i)}
// Check overflow if sign of both are same
if res.i.BitLen() > 255 {
if res.i.BitLen() > maxBitLen {
panic("Int overflow")
}
return
Expand Down
20 changes: 20 additions & 0 deletions types/int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,23 @@ func TestSafeSub(t *testing.T) {
)
}
}

func TestSerializationOverflow(t *testing.T) {
bx, _ := new(big.Int).SetString("91888242871839275229946405745257275988696311157297823662689937894645226298583", 10)
x := Int{bx}
y := new(Int)

// require amino deserialization to fail due to overflow
xStr, err := x.MarshalAmino()
require.NoError(t, err)

err = y.UnmarshalAmino(xStr)
require.Error(t, err)

// require JSON deserialization to fail due to overflow
bz, err := x.MarshalJSON()
require.NoError(t, err)

err = y.UnmarshalJSON(bz)
require.Error(t, err)
}

0 comments on commit fd5e7b9

Please sign in to comment.