From 376f333e7833d3e47f4cccbb4950a02dffcec8c6 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 26 Apr 2023 20:32:41 +0800 Subject: [PATCH 1/3] fix: check mismatch error after recusive --- decoder/assembler_amd64_go116.go | 15 +++++++++++++-- decoder/assembler_amd64_go117.go | 20 +++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/decoder/assembler_amd64_go116.go b/decoder/assembler_amd64_go116.go index a839b1620..fab5d62cd 100644 --- a/decoder/assembler_amd64_go116.go +++ b/decoder/assembler_amd64_go116.go @@ -458,6 +458,7 @@ var ( var ( _V_stackOverflow = jit.Imm(int64(uintptr(unsafe.Pointer(&stackOverflow)))) _I_json_UnsupportedValueError = jit.Itab(_T_error, reflect.TypeOf(new(json.UnsupportedValueError))) + _I_json_MismatchTypeError = jit.Itab(_T_error, reflect.TypeOf(new(MismatchTypeError))) ) func (self *_Assembler) type_error() { @@ -472,6 +473,10 @@ func (self *_Assembler) type_error() { func (self *_Assembler) mismatch_error() { self.Link(_LB_mismatch_error) // _type_error: + self.Emit("MOVQ", _VAR_et, _ET) // MOVQ _VAR_et, _ET + self.Emit("MOVQ", _VAR_ic, _EP) // MOVQ _VAR_ic, _EP + self.Emit("CMPQ", _ET, _I_json_MismatchTypeError) // CMPQ _ET, _I_json_MismatchType + self.Sjmp("JE" , _LB_error) // JE _LB_error self.Emit("MOVQ", _ARG_sp, _AX) self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) self.Emit("MOVQ", _ARG_sl, _CX) @@ -1128,9 +1133,15 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { self.call_go(_F_decodeTypedPointer) // CALL_GO decodeTypedPointer self.Emit("MOVQ" , jit.Ptr(_SP, 64), _ET) // MOVQ 64(SP), ET self.Emit("MOVQ" , jit.Ptr(_SP, 72), _EP) // MOVQ 72(SP), EP - self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET - self.Sjmp("JNZ" , _LB_error) // JNZ _error self.Emit("MOVQ" , jit.Ptr(_SP, 56), _IC) // MOVQ 56(SP), IC + self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET + self.Sjmp("JE", "_decode_dynamic_end_{n}") // JE, _decode_dynamic_end_{n} + self.Emit("CMPQ", _ET, _I_json_MismatchTypeError) + self.Sjmp("JNE" , _LB_error) // JNE LB_error + self.Emit("MOVQ", _EP, _VAR_ic) // MOVQ EP, VAR_ic + self.Emit("MOVQ", _ET, _VAR_et) // MOVQ ET, VAR_et + self.Link("_decode_dynamic_end_{n}") + } /** OpCode Assembler Functions **/ diff --git a/decoder/assembler_amd64_go117.go b/decoder/assembler_amd64_go117.go index 5e852e530..90b4f6de8 100644 --- a/decoder/assembler_amd64_go117.go +++ b/decoder/assembler_amd64_go117.go @@ -348,8 +348,8 @@ func (self *_Assembler) epilogue() { self.Emit("MOVQ", _EP, _CX) // MOVQ BX, CX self.Emit("MOVQ", _ET, _BX) // MOVQ AX, BX self.Emit("MOVQ", _IC, _AX) // MOVQ IC, AX - self.Emit("MOVQ", jit.Imm(0), _ARG_sp) // MOVQ $0, sv.p<>+48(FP) - self.Emit("MOVQ", jit.Imm(0), _ARG_vp) // MOVQ $0, sv.p<>+48(FP) + self.Emit("MOVQ", jit.Imm(0), _ARG_sp) // MOVQ $0, sv.p<>+48(FP) + self.Emit("MOVQ", jit.Imm(0), _ARG_vp) // MOVQ $0, sv.p<>+48(FP) self.Emit("MOVQ", jit.Imm(0), _ARG_sv_p) // MOVQ $0, sv.p<>+48(FP) self.Emit("MOVQ", jit.Imm(0), _ARG_vk) // MOVQ $0, vk<>+64(FP) self.Emit("MOVQ", jit.Ptr(_SP, _FP_offs), _BP) // MOVQ _FP_offs(SP), BP @@ -480,6 +480,7 @@ var ( var ( _V_stackOverflow = jit.Imm(int64(uintptr(unsafe.Pointer(&stackOverflow)))) _I_json_UnsupportedValueError = jit.Itab(_T_error, reflect.TypeOf(new(json.UnsupportedValueError))) + _I_json_MismatchTypeError = jit.Itab(_T_error, reflect.TypeOf(new(MismatchTypeError))) ) func (self *_Assembler) type_error() { @@ -489,7 +490,11 @@ func (self *_Assembler) type_error() { } func (self *_Assembler) mismatch_error() { - self.Link(_LB_mismatch_error) // _type_error: + self.Link(_LB_mismatch_error) // _type_error: + self.Emit("MOVQ", _VAR_et, _ET) // MOVQ _VAR_et, _ET + self.Emit("MOVQ", _VAR_ic, _EP) // MOVQ _VAR_ic, _EP + self.Emit("CMPQ", _ET, _I_json_MismatchTypeError) // CMPQ _ET, _I_json_MismatchType + self.Sjmp("JE" , _LB_error) // JE _LB_error self.Emit("MOVQ", _ARG_sp, _AX) self.Emit("MOVQ", _ARG_sl, _BX) self.Emit("MOVQ", _VAR_ic, _CX) @@ -1119,7 +1124,7 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { self.Emit("MOVQ", _ARG_sp, _AX) // MOVQ sp, AX self.Emit("MOVQ", _ARG_sl, _BX) // MOVQ sp, BX self.Emit("MOVQ" , _IC, _CX) // MOVQ IC, CX - self.Emit("MOVQ" , _ST, _R8) // MOVQ ST, R8 + self.Emit("MOVQ" , _ST, _R8) // MOVQ ST, R8 self.Emit("MOVQ" , _ARG_fv, _R9) // MOVQ fv, R9 self.save(_REG_rt...) self.Emit("MOVQ", _F_decodeTypedPointer, _IL) // MOVQ ${fn}, R11 @@ -1129,7 +1134,12 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { self.Emit("MOVQ" , _BX, _ET) // MOVQ BX, ET self.Emit("MOVQ" , _CX, _EP) // MOVQ CX, EP self.Emit("TESTQ", _ET, _ET) // TESTQ ET, ET - self.Sjmp("JNZ" , _LB_error) // JNZ _error + self.Sjmp("JE", "_decode_dynamic_end_{n}") // JE, _decode_dynamic_end_{n} + self.Emit("CMPQ", _ET, _I_json_MismatchTypeError) + self.Sjmp("JNE" , _LB_error) // JNE LB_error + self.Emit("MOVQ", _EP, _VAR_ic) // MOVQ EP, VAR_ic + self.Emit("MOVQ", _ET, _VAR_et) // MOVQ ET, VAR_et + self.Link("_decode_dynamic_end_{n}") } /** OpCode Assembler Functions **/ From 0e9aaba825e9fe0aaade52efec4aae2c2ed22a28 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 26 Apr 2023 20:38:16 +0800 Subject: [PATCH 2/3] fix: add tests --- issue_test/issue406_test.go | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 issue_test/issue406_test.go diff --git a/issue_test/issue406_test.go b/issue_test/issue406_test.go new file mode 100644 index 000000000..21e0ca5d8 --- /dev/null +++ b/issue_test/issue406_test.go @@ -0,0 +1,54 @@ +/* + * Copyright 2023 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 ( + "testing" + "encoding/json" + `github.com/davecgh/go-spew/spew` + `github.com/stretchr/testify/require` + + "github.com/bytedance/sonic" +) +var mapdata = `{ + "ptrslice": [{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": "4"}] + }`; + + +type FooId struct { + Id int `json:"id"` +} + +func TestUnmarshalErrorInMapSlice(t *testing.T) { + var a, b map[string][]FooId + se := json.Unmarshal([]byte(mapdata), &a) + je := sonic.Unmarshal([]byte(mapdata), &b) + spew.Dump(se, a) // len(a) = 4 + spew.Dump(je, b) // len(b) = 1 + require.Equal(t, a, b); +} + +var slicedata = `[{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": 4}]`; + +func TestUnmarshalErrorInSlice(t *testing.T) { + var a, b []*FooId + je := json.Unmarshal([]byte(slicedata), &a) + se := sonic.Unmarshal([]byte(slicedata), &b) + spew.Dump("sonic ", se, b) + spew.Dump("json ", je, a) + require.Equal(t, a, b); +} From 49e01e432e9948abf10ef832735fc32d2bf3914e Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 26 Apr 2023 20:39:50 +0800 Subject: [PATCH 3/3] format --- decoder/assembler_amd64_go117.go | 2 +- issue_test/issue406_test.go | 34 ++++++++++++-------------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/decoder/assembler_amd64_go117.go b/decoder/assembler_amd64_go117.go index 90b4f6de8..2862e5de2 100644 --- a/decoder/assembler_amd64_go117.go +++ b/decoder/assembler_amd64_go117.go @@ -1124,7 +1124,7 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { self.Emit("MOVQ", _ARG_sp, _AX) // MOVQ sp, AX self.Emit("MOVQ", _ARG_sl, _BX) // MOVQ sp, BX self.Emit("MOVQ" , _IC, _CX) // MOVQ IC, CX - self.Emit("MOVQ" , _ST, _R8) // MOVQ ST, R8 + self.Emit("MOVQ" , _ST, _R8) // MOVQ ST, R8 self.Emit("MOVQ" , _ARG_fv, _R9) // MOVQ fv, R9 self.save(_REG_rt...) self.Emit("MOVQ", _F_decodeTypedPointer, _IL) // MOVQ ${fn}, R11 diff --git a/issue_test/issue406_test.go b/issue_test/issue406_test.go index 21e0ca5d8..7c3213ebb 100644 --- a/issue_test/issue406_test.go +++ b/issue_test/issue406_test.go @@ -17,38 +17,30 @@ package issue_test import ( - "testing" - "encoding/json" - `github.com/davecgh/go-spew/spew` - `github.com/stretchr/testify/require` - - "github.com/bytedance/sonic" + `testing` + `encoding/json` + `github.com/stretchr/testify/require` + `github.com/bytedance/sonic` ) -var mapdata = `{ - "ptrslice": [{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": "4"}] - }`; - type FooId struct { - Id int `json:"id"` + Id int `json:"id"` } func TestUnmarshalErrorInMapSlice(t *testing.T) { - var a, b map[string][]FooId - se := json.Unmarshal([]byte(mapdata), &a) - je := sonic.Unmarshal([]byte(mapdata), &b) - spew.Dump(se, a) // len(a) = 4 - spew.Dump(je, b) // len(b) = 1 - require.Equal(t, a, b); + var a, b map[string][]FooId + mapdata := `{"ptrslice": [{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": "4"}]}` + se := json.Unmarshal([]byte(mapdata), &a) + je := sonic.Unmarshal([]byte(mapdata), &b) + require.Equal(t, se == nil, je == nil); + require.Equal(t, a, b); } -var slicedata = `[{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": 4}]`; - func TestUnmarshalErrorInSlice(t *testing.T) { var a, b []*FooId + slicedata := `[{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": 4}]` je := json.Unmarshal([]byte(slicedata), &a) se := sonic.Unmarshal([]byte(slicedata), &b) - spew.Dump("sonic ", se, b) - spew.Dump("json ", je, a) + require.Equal(t, se == nil, je == nil); require.Equal(t, a, b); }