Merge PR #3552: General Sanitization & Gas Cost Review

This commit is contained in:
Alexander Bezobchuk 2019-02-08 14:33:29 -08:00 committed by Christopher Goes
parent e7e3c32204
commit fd5e7b9b80
3 changed files with 48 additions and 10 deletions

View File

@ -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

View File

@ -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)
}
@ -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
@ -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
}
@ -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}
@ -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
}
@ -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}
@ -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
@ -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
@ -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

View File

@ -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)
}