diff --git a/math/CHANGELOG.md b/math/CHANGELOG.md index 10dbe4a437c5..5d72be38e3f1 100644 --- a/math/CHANGELOG.md +++ b/math/CHANGELOG.md @@ -39,7 +39,9 @@ Ref: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.j ### Bug Fixes * [#16266](https://github.com/cosmos/cosmos-sdk/pull/16266) fix: legacy dec power mut zero exponent precision. +* [#17352](https://github.com/cosmos/cosmos-sdk/pull/17352) Ensure that modifying the argument to `NewIntFromBigInt` doesn't mutate the returned value. * [#18211](https://github.com/cosmos/cosmos-sdk/pull/18211) RelativePow now returns 1 when 0^0, before it was returning the scale factor. +* [#18214](https://github.com/cosmos/cosmos-sdk/pull/18214) Ensure that modifying the argument to ## [math/v1.0.1](https://github.com/cosmos/cosmos-sdk/releases/tag/math/v1.0.1) - 2023-05-15 diff --git a/math/int.go b/math/int.go index dc945b13d283..9cfab3175471 100644 --- a/math/int.go +++ b/math/int.go @@ -105,6 +105,7 @@ func NewIntFromUint64(n uint64) Int { // NewIntFromBigInt constructs Int from big.Int. If the provided big.Int is nil, // it returns an empty instance. This function panics if the bit length is > 256. +// Note, the caller can safely mutate the argument after this function returns. func NewIntFromBigInt(i *big.Int) Int { if i == nil { return Int{} @@ -113,7 +114,7 @@ func NewIntFromBigInt(i *big.Int) Int { if i.BitLen() > MaxBitLen { panic("NewIntFromBigInt() out of bound") } - return Int{i} + return Int{new(big.Int).Set(i)} } // NewIntFromString constructs Int from string diff --git a/math/int_test.go b/math/int_test.go index 56b05cc69f94..8daea2f25e9d 100644 --- a/math/int_test.go +++ b/math/int_test.go @@ -43,6 +43,19 @@ func (s *intTestSuite) TestFromUint64() { } } +func (s *intTestSuite) TestNewIntFromBigInt() { + i := math.NewIntFromBigInt(nil) + s.Require().True(i.IsNil()) + + r := big.NewInt(42) + i = math.NewIntFromBigInt(r) + s.Require().Equal(r, i.BigInt()) + + // modify r and ensure i doesn't change + r = r.SetInt64(100) + s.Require().NotEqual(r, i.BigInt()) +} + func (s *intTestSuite) TestIntPanic() { // Max Int = 2^256-1 = 1.1579209e+77 // Min Int = -(2^256-1) = -1.1579209e+77 diff --git a/math/uint.go b/math/uint.go index 0a61646ae188..b347a84653dd 100644 --- a/math/uint.go +++ b/math/uint.go @@ -235,7 +235,7 @@ func checkNewUint(i *big.Int) (Uint, error) { if err := UintOverflow(i); err != nil { return Uint{}, err } - return Uint{i}, nil + return Uint{new(big.Int).Set(i)}, nil } // RelativePow raises x to the power of n, where x (and the result, z) are scaled by factor b diff --git a/math/uint_test.go b/math/uint_test.go index 0c464433a074..3ae815e0e662 100644 --- a/math/uint_test.go +++ b/math/uint_test.go @@ -261,6 +261,16 @@ func (s *uintTestSuite) TestParseUint() { } } +func (s *uintTestSuite) TestNewUintFromBigInt() { + r := big.NewInt(42) + i := sdkmath.NewUintFromBigInt(r) + s.Require().Equal(r, i.BigInt()) + + // modify r and ensure i doesn't change + r = r.SetInt64(100) + s.Require().NotEqual(r, i.BigInt()) +} + func randuint() sdkmath.Uint { return sdkmath.NewUint(rand.Uint64()) }