From ebbe7589ca6e2e39e915da3295a22b1a754f1871 Mon Sep 17 00:00:00 2001 From: liu Date: Sat, 6 May 2023 16:20:23 +0800 Subject: [PATCH] fix: check mismatch error after recursive (#407) * fix: check mismatch error after recusive * fix: add tests * format --------- Co-authored-by: liuqiang --- decoder/assembler_amd64_go116.go | 15 +++++++++-- decoder/assembler_amd64_go117.go | 18 ++++++++++--- issue_test/issue406_test.go | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 issue_test/issue406_test.go 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..2862e5de2 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) @@ -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 **/ diff --git a/issue_test/issue406_test.go b/issue_test/issue406_test.go new file mode 100644 index 000000000..7c3213ebb --- /dev/null +++ b/issue_test/issue406_test.go @@ -0,0 +1,46 @@ +/* + * 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/stretchr/testify/require` + `github.com/bytedance/sonic` +) + +type FooId struct { + Id int `json:"id"` +} + +func TestUnmarshalErrorInMapSlice(t *testing.T) { + 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); +} + +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) + require.Equal(t, se == nil, je == nil); + require.Equal(t, a, b); +}