From 813f92afd32d0047d72cede7313e317f14ca074e Mon Sep 17 00:00:00 2001 From: dusan-maksimovic Date: Tue, 30 Jan 2024 12:22:07 +0100 Subject: [PATCH] Ensure that modifying the argument to `NewUIntFromBigInt` and `NewIntFromBigInt` doesn't mutate the returned value --- math/int.go | 3 ++- math/int_test.go | 13 +++++++++++++ math/uint.go | 2 +- math/uint_test.go | 10 ++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/math/int.go b/math/int.go index 6811893f7a47..0727ff572e44 100644 --- a/math/int.go +++ b/math/int.go @@ -104,6 +104,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{} @@ -112,7 +113,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 5af450cb6c19..880eff2c0fc0 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 81da2d9ef8d5..0c121fb72f2b 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 428672cb2cea..6d32ef044a6f 100644 --- a/math/uint_test.go +++ b/math/uint_test.go @@ -260,6 +260,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()) }