From a29019de9d6dc5a3fdefe67f29a36d9ecf5a943f Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sat, 30 Oct 2021 10:17:58 -0500 Subject: [PATCH] Fix binary decoding of very large numerics. fixes #133 --- numeric.go | 6 +++--- numeric_test.go | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/numeric.go b/numeric.go index a7efa704..f5260548 100644 --- a/numeric.go +++ b/numeric.go @@ -452,11 +452,11 @@ func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error { } rp := 0 - ndigits := int16(binary.BigEndian.Uint16(src[rp:])) + ndigits := binary.BigEndian.Uint16(src[rp:]) rp += 2 weight := int16(binary.BigEndian.Uint16(src[rp:])) rp += 2 - sign := uint16(binary.BigEndian.Uint16(src[rp:])) + sign := binary.BigEndian.Uint16(src[rp:]) rp += 2 dscale := int16(binary.BigEndian.Uint16(src[rp:])) rp += 2 @@ -504,7 +504,7 @@ func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error { exp := (int32(weight) - int32(ndigits) + 1) * 4 if dscale > 0 { - fracNBaseDigits := ndigits - weight - 1 + fracNBaseDigits := int16(int32(ndigits) - int32(weight) - 1) fracDecimalDigits := fracNBaseDigits * 4 if dscale > fracDecimalDigits { diff --git a/numeric_test.go b/numeric_test.go index 81595cb3..fff5a2e0 100644 --- a/numeric_test.go +++ b/numeric_test.go @@ -117,6 +117,10 @@ func TestNumericNormalize(t *testing.T) { } func TestNumericTranscode(t *testing.T) { + max := new(big.Int).Exp(big.NewInt(10), big.NewInt(147454), nil) + max.Add(max, big.NewInt(1)) + longestNumeric := &pgtype.Numeric{Int: max, Exp: -16383, Status: pgtype.Present} + testutil.TestSuccessfulTranscodeEqFunc(t, "numeric", []interface{}{ &pgtype.Numeric{NaN: true, Status: pgtype.Present}, @@ -151,6 +155,9 @@ func TestNumericTranscode(t *testing.T) { &pgtype.Numeric{Int: mustParseBigInt(t, "423409823409243892349028349023482934092340892390101"), Exp: -92, Status: pgtype.Present}, &pgtype.Numeric{Int: mustParseBigInt(t, "23409823409243892349028349023482934092340892390101"), Exp: -93, Status: pgtype.Present}, &pgtype.Numeric{Int: mustParseBigInt(t, "3409823409243892349028349023482934092340892390101"), Exp: -94, Status: pgtype.Present}, + + longestNumeric, + &pgtype.Numeric{Status: pgtype.Null}, }, func(aa, bb interface{}) bool { a := aa.(pgtype.Numeric)