2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-21 00:46:43 +08:00

fix: parsing to float64 when the integer(int64) overflow

This commit is contained in:
liuqiang 2021-07-23 17:32:26 +08:00 committed by Oxygen
parent f9632ab873
commit e88411dafe
6 changed files with 818 additions and 846 deletions

View file

@ -34,8 +34,8 @@ type atofTest struct {
// Tests from Go strconv package, https://github.com/golang/go/blob/master/src/strconv/atof_test.go
// All tests are passed in Go encoding/json.
var atoftests = []atofTest{
{"1.234e", "1.234", nil},
{"1i", "1", nil},
{"1.234e", "", nil}, // error
{"1i", "1", nil}, // pass
{"1", "1", nil},
{"1e23", "1e+23", nil},
{"1E23", "1e+23", nil},
@ -140,19 +140,25 @@ var atoftests = []atofTest{
{"1090544144181609348671888949248", "1.0905441441816093e+30", nil},
// slightly above, rounds up
{"1090544144181609348835077142190", "1.0905441441816094e+30", nil},
// Corner case between int64 and float64 for the input
{"9223372036854775807", "9223372036854775807", nil}, // max int64: (1 << 63) - 1
{"9223372036854775808", "9223372036854775808", nil},
{"-9223372036854775808", "-9223372036854775808", nil}, // min int64: 1 << 63
{"-9223372036854775809", "-9223372036854775809", nil},
}
func TestDecodeFloat(t *testing.T) {
var sonicout, stdout interface{}
for _, tt := range atoftests {
for i, tt := range atoftests {
// default float64
var sonicout, stdout interface{}
sonicerr := decoder.NewDecoder(tt.in).Decode(&sonicout)
stderr := json.NewDecoder(strings.NewReader(tt.in)).Decode(&stdout)
if !reflect.DeepEqual(sonicout, stdout) {
t.Fatalf("Test %#v\ngot:\n %#v\nexp:\n %#v\n", tt.in, sonicout, stdout)
t.Fatalf("Test %d, %#v\ngot:\n %#v\nexp:\n %#v\n", i, tt.in, sonicout, stdout)
}
if !reflect.DeepEqual(sonicerr == nil, stderr == nil) {
t.Fatalf("Test %#v\ngot:\n %#v\nexp:\n %#v\n", tt.in, sonicerr, stderr)
t.Fatalf("Test %d, %#v\ngot:\n %#v\nexp:\n %#v\n", i, tt.in, sonicerr, stderr)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -19,16 +19,16 @@ var (
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 238
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 4951
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16081
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16116
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13759
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15993
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 16028
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13671
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3731
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5972
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9426
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11985
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13209
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12001
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13121
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11032
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13486
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13398
)
var (

File diff suppressed because it is too large Load diff

View file

@ -19,16 +19,16 @@ var (
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 366
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5299
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18501
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18536
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15701
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18413
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18448
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15613
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3979
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 7136
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11379
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13927
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15151
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13943
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15063
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13090
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15428
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15340
)
var (

View file

@ -412,12 +412,12 @@ void vstring(const GoString *src, long *p, JsonState *ret) {
man_nd++; \
} else { \
exp10++; \
} \
}
#define add_float_to_mantissa(man, man_nd, exp10, dig) \
man = man * 10 + dig; \
man_nd++; \
exp10--; \
exp10--;
#define parse_float_digits(val, sgn, ...) \
while (i < n && s[i] >= '0' && s[i] <= '9' __VA_ARGS__) { \
@ -490,7 +490,9 @@ static inline int is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
return 0;
}
f *= sgn;
if (sgn == -1) {
f = -f;
}
*val = 0;
if (exp == 0 || man == 0) {
@ -563,12 +565,6 @@ void vnumber(const GoString *src, long *p, JsonState *ret) {
check_eof()
check_sign(sgn = -1)
/* zero */
if (i + 1 == n && s[i] == '0') {
i++;
goto out;
}
/* check for leading zero */
check_digit()
check_leading_zero()
@ -634,10 +630,8 @@ void vnumber(const GoString *src, long *p, JsonState *ret) {
exp10 += exp * esm;
}
out:
if (ret->vt == V_INTEGER) {
/* if INT64_MIN <= man * sgn <= INT64_MAX */
if ( exp10 == 0 && (((man & ((uint64_t)1 << 63)) == 0) || ((man & sgn) == man))) {
if ( exp10 == 0 && (man >> 63) == 0) {
ret->iv = (int64_t)man * sgn;
ret->dv = (double)(ret->iv);
} else { // integer overflow