diff --git a/decoder/assembler_amd64_go116.go b/decoder/assembler_amd64_go116.go index 7ac7974..7e02b1d 100644 --- a/decoder/assembler_amd64_go116.go +++ b/decoder/assembler_amd64_go116.go @@ -581,6 +581,15 @@ func (self *_Assembler) check_err() { self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v } +func (self *_Assembler) check_err_num() { + self.Emit("MOVQ" , _VAR_st_Vt, _AX) // MOVQ st.Vt, AX + self.Emit("TESTQ", _AX, _AX) // CMPQ AX, ${native.V_STRING} + self.Sjmp("JNS" , "check_err_end_{n}") + self.Emit("CMPQ" , _AX, jit.Imm(-int64(types.ERR_FLOAT_INFINITY))) + self.Sjmp("JNE" , _LB_parsing_error_v) + self.Link("check_err_end_{n}") +} + func (self *_Assembler) check_eof(d int64) { if d == 1 { self.Emit("CMPQ", _IC, _IL) // CMPQ IC, IL @@ -1171,7 +1180,8 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) { self.Emit("MOVQ", jit.Imm(1), _VAR_fl) self.Emit("ADDQ", jit.Imm(1), _IC) self.Link("_parse_number_{n}") - self.parse_number() // PARSE NUMBER + self.call_vf(_F_vnumber) // call vnumber + self.check_err_num() self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0 self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv) self.Sjmp("JNC", "_num_write_{n}") diff --git a/decoder/assembler_amd64_go117.go b/decoder/assembler_amd64_go117.go index 3d254bf..c153e08 100644 --- a/decoder/assembler_amd64_go117.go +++ b/decoder/assembler_amd64_go117.go @@ -591,6 +591,15 @@ func (self *_Assembler) check_err() { self.Sjmp("JS" , _LB_parsing_error_v) // JNE _parsing_error_v } +func (self *_Assembler) check_err_num() { + self.Emit("MOVQ" , _VAR_st_Vt, _AX) // MOVQ st.Vt, AX + self.Emit("TESTQ", _AX, _AX) // CMPQ AX, ${native.V_STRING} + self.Sjmp("JNS" , "check_err_end_{n}") + self.Emit("CMPQ" , _AX, jit.Imm(-int64(types.ERR_FLOAT_INFINITY))) + self.Sjmp("JNE" , _LB_parsing_error_v) + self.Link("check_err_end_{n}") +} + func (self *_Assembler) check_eof(d int64) { if d == 1 { self.Emit("CMPQ", _IC, _IL) // CMPQ IC, IL @@ -1168,7 +1177,8 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) { self.Emit("MOVQ", jit.Imm(1), _VAR_fl) self.Emit("ADDQ", jit.Imm(1), _IC) self.Link("_parse_number_{n}") - self.parse_number() // PARSE NUMBER + self.call_vf(_F_vnumber) + self.check_err_num() self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0 self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv) self.Sjmp("JNC", "_num_write_{n}") diff --git a/decoder/generic_amd64_go116.go b/decoder/generic_amd64_go116.go index 61b68f0..4f64717 100644 --- a/decoder/generic_amd64_go116.go +++ b/decoder/generic_amd64_go116.go @@ -273,8 +273,14 @@ func (self *_ValueDecoder) compile() { /* check for errors */ self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX - self.Sjmp("JS" , "_parsing_error") // JS _parsing_error self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype + self.Sjmp("JNS" , "_not_sign") // JNS + self.Emit("CMPQ" , _AX, jit.Imm(-int64(types.ERR_FLOAT_INFINITY))) + self.Sjmp("JNE" , "_parsing_error") + self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df + self.Sjmp("JNC" , "_parsing_error") + self.Emit("MOVQ" , jit.Imm(int64(types.V_DOUBLE)), _AX) + self.Link("_not_sign") self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype diff --git a/decoder/generic_amd64_go117.go b/decoder/generic_amd64_go117.go index 775d3b4..093800d 100644 --- a/decoder/generic_amd64_go117.go +++ b/decoder/generic_amd64_go117.go @@ -288,8 +288,14 @@ func (self *_ValueDecoder) compile() { /* check for errors */ self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX - self.Sjmp("JS" , "_parsing_error") // JS _parsing_error self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype + self.Sjmp("JNS" , "_not_sign") // JNS + self.Emit("CMPQ" , _AX, jit.Imm(-int64(types.ERR_FLOAT_INFINITY))) + self.Sjmp("JNE" , "_parsing_error") + self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df + self.Sjmp("JNC" , "_parsing_error") + self.Emit("MOVQ" , jit.Imm(int64(types.V_DOUBLE)), _AX) + self.Link("_not_sign") self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype diff --git a/issue_test/issue206_test.go b/issue_test/issue206_test.go new file mode 100644 index 0000000..0699b04 --- /dev/null +++ b/issue_test/issue206_test.go @@ -0,0 +1,57 @@ +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package issue_test + +import ( + `bytes` + `encoding/json` + `strings` + `testing` + + `github.com/stretchr/testify/require` + + `github.com/bytedance/sonic` + `github.com/bytedance/sonic/decoder` +) + +var issue_19x_idata = "\"" + strings.Repeat("9", 1000) + "\"" +var issue_19x_fdata = "\"" + strings.Repeat("9", 100) + "." + strings.Repeat("9", 1000) + "\"" +var issue_19x_ndata = strings.Repeat("9", 1000) + +func TestDecodeLongStringToJsonNumber(t *testing.T) { + var objs, obje json.Number + errs := sonic.UnmarshalString(issue_19x_idata, &objs) + erre := json.Unmarshal([]byte(issue_19x_idata), &obje) + require.Equal(t, erre, errs) + require.Equal(t, obje, objs) + + var fobjs, fobje json.Number + errs = sonic.UnmarshalString(issue_19x_fdata, &fobjs) + erre = json.Unmarshal([]byte(issue_19x_fdata), &fobje) + require.Equal(t, erre, errs) + require.Equal(t, fobje, fobjs) + + var iobjs, iobje interface{} + dc := decoder.NewDecoder(issue_19x_ndata) + dc.UseNumber() + errs = dc.Decode(&iobjs) + r := json.NewDecoder(bytes.NewBufferString(issue_19x_ndata)) + r.UseNumber() + erre = r.Decode(&iobje) + require.Equal(t, erre, errs) + require.Equal(t, iobje, iobjs) +} \ No newline at end of file