From e4fa084bf8af8d5c759e22da1022bbc39a5c8b75 Mon Sep 17 00:00:00 2001 From: ozpool Date: Wed, 17 Jun 2026 11:59:47 +0530 Subject: [PATCH] fix(utils): avoid int64 overflow for uint and uint64 in ToDecimal decimal.New(int64(v), 0) silently wraps large unsigned values: int64(math.MaxUint64) == -1, producing wrong negative decimals. Switch uint and uint64 cases to decimal.NewFromUint64, which handles the full unsigned range correctly. uint8/16/32 are unaffected since their maximum values fit in int64. --- core/utils/decimal.go | 4 ++-- core/utils/decimal_test.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/utils/decimal.go b/core/utils/decimal.go index 1ff6f645738..811749bd161 100644 --- a/core/utils/decimal.go +++ b/core/utils/decimal.go @@ -27,7 +27,7 @@ func ToDecimal(input any) (decimal.Decimal, error) { case int64: return decimal.New(v, 0), nil case uint: - return decimal.New(int64(v), 0), nil + return decimal.NewFromUint64(uint64(v)), nil case uint8: return decimal.New(int64(v), 0), nil case uint16: @@ -35,7 +35,7 @@ func ToDecimal(input any) (decimal.Decimal, error) { case uint32: return decimal.New(int64(v), 0), nil case uint64: - return decimal.New(int64(v), 0), nil + return decimal.NewFromUint64(v), nil case float64: if !validFloat(v) { return decimal.Decimal{}, errors.Errorf("invalid float %v, cannot convert to decimal", v) diff --git a/core/utils/decimal_test.go b/core/utils/decimal_test.go index 068376ebbba..0acb71f9c0e 100644 --- a/core/utils/decimal_test.go +++ b/core/utils/decimal_test.go @@ -7,6 +7,7 @@ import ( "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDecimal(t *testing.T) { @@ -56,3 +57,17 @@ func TestDecimal(t *testing.T) { } } } + +func TestDecimalUint64NoOverflow(t *testing.T) { + t.Parallel() + + // Values above math.MaxInt64 were silently corrupted: int64(math.MaxUint64) == -1. + want, _ := decimal.NewFromString("18446744073709551615") // math.MaxUint64 + got, err := ToDecimal(uint64(math.MaxUint64)) + require.NoError(t, err) + assert.True(t, got.Equal(want), "uint64(MaxUint64): got %s, want %s", got, want) + + got, err = ToDecimal(uint(math.MaxUint64)) + require.NoError(t, err) + assert.True(t, got.Equal(want), "uint(MaxUint64): got %s, want %s", got, want) +}