From dff8e500855e5ad1e1f9b3ceee92145a2dee8cb1 Mon Sep 17 00:00:00 2001 From: Halimao <1065621723@qq.com> Date: Wed, 19 Jun 2024 17:06:52 +0800 Subject: [PATCH] common: using `ParseUint` instead of `ParseInt` (#30020) Since Decimal is defined as unsiged `uint64`, we should use `strconv.ParseUint` instead of `strconv.ParseInt` during unmarshalling. --------- Co-authored-by: Martin Holst Swende --- common/types.go | 2 +- common/types_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/common/types.go b/common/types.go index 60977e8486..c335391355 100644 --- a/common/types.go +++ b/common/types.go @@ -435,7 +435,7 @@ func (d *Decimal) UnmarshalJSON(input []byte) error { if !isString(input) { return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))} } - if i, err := strconv.ParseInt(string(input[1:len(input)-1]), 10, 64); err == nil { + if i, err := strconv.ParseUint(string(input[1:len(input)-1]), 10, 64); err == nil { *d = Decimal(i) return nil } else { diff --git a/common/types_test.go b/common/types_test.go index 3262f54931..1faf101977 100644 --- a/common/types_test.go +++ b/common/types_test.go @@ -20,6 +20,7 @@ import ( "bytes" "encoding/json" "fmt" + "math" "math/big" "strings" "testing" @@ -405,3 +406,29 @@ func BenchmarkPrettyDuration(b *testing.B) { } b.Logf("Post %s", a) } + +func TestDecimalUnmarshalJSON(t *testing.T) { + // These should error + for _, tc := range []string{``, `"`, `""`, `"-1"`} { + if err := new(Decimal).UnmarshalJSON([]byte(tc)); err == nil { + t.Errorf("input %s should cause error", tc) + } + } + // These should succeed + for _, tc := range []struct { + input string + want uint64 + }{ + {`"0"`, 0}, + {`"9223372036854775807"`, math.MaxInt64}, + {`"18446744073709551615"`, math.MaxUint64}, + } { + have := new(Decimal) + if err := have.UnmarshalJSON([]byte(tc.input)); err != nil { + t.Errorf("input %q triggered error: %v", tc.input, err) + } + if uint64(*have) != tc.want { + t.Errorf("input %q, have %d want %d", tc.input, *have, tc.want) + } + } +}