From b9719709b55995648d7a3d07fd8ec9c88346aec9 Mon Sep 17 00:00:00 2001 From: liuq19 Date: Fri, 23 Aug 2024 22:15:21 +0800 Subject: [PATCH] fix: corrupted mismatch type error in jit --- .../decoder/jitdec/assembler_regabi_amd64.go | 6 +-- .../decoder/jitdec/generic_regabi_amd64.go | 1 - internal/decoder/jitdec/pools.go | 2 + issue_test/issue692_test.go | 47 +++++++++++++++++++ loader/loader_latest.go | 2 +- 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 issue_test/issue692_test.go diff --git a/internal/decoder/jitdec/assembler_regabi_amd64.go b/internal/decoder/jitdec/assembler_regabi_amd64.go index 3a2b718e9..8a43d868b 100644 --- a/internal/decoder/jitdec/assembler_regabi_amd64.go +++ b/internal/decoder/jitdec/assembler_regabi_amd64.go @@ -385,7 +385,7 @@ func (self *_Assembler) prologue() { var ( _REG_go = []obj.Addr { _ST, _VP, _IP, _IL, _IC } - _REG_rt = []obj.Addr { _ST, _VP, _IP, _IL, _IC, _IL } + _REG_rt = []obj.Addr { _ST, _VP, _IP, _IL, _IC } ) func (self *_Assembler) save(r ...obj.Addr) { @@ -492,9 +492,9 @@ 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("MOVQ", _I_json_MismatchTypeError, _CX) // MOVQ _I_json_MismatchType, CX self.Emit("CMPQ", _ET, _CX) // CMPQ ET, CX + self.Emit("MOVQ", jit.Ptr(_ST, _EpOffset), _EP) // MOVQ stack.Ep, EP self.Sjmp("JE" , _LB_error) // JE _LB_error self.Emit("MOVQ", _ARG_sp, _AX) self.Emit("MOVQ", _ARG_sl, _BX) @@ -1147,8 +1147,8 @@ func (self *_Assembler) decode_dynamic(vt obj.Addr, vp obj.Addr) { self.Emit("MOVQ", _I_json_MismatchTypeError, _CX) // MOVQ _I_json_MismatchTypeError, CX self.Emit("CMPQ", _ET, _CX) // CMPQ ET, CX 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.WriteRecNotAX(14, _EP, jit.Ptr(_ST, _EpOffset), false, false) // MOVQ EP, stack.Ep self.Link("_decode_dynamic_end_{n}") } diff --git a/internal/decoder/jitdec/generic_regabi_amd64.go b/internal/decoder/jitdec/generic_regabi_amd64.go index 2c21944a5..e6d5e3e84 100644 --- a/internal/decoder/jitdec/generic_regabi_amd64.go +++ b/internal/decoder/jitdec/generic_regabi_amd64.go @@ -186,7 +186,6 @@ var ( _T_slice = jit.Type(reflect.TypeOf(([]interface{})(nil))) _T_string = jit.Type(reflect.TypeOf("")) _T_number = jit.Type(reflect.TypeOf(json.Number(""))) - _T_miserr = jit.Type(reflect.TypeOf(MismatchTypeError{})) _T_float64 = jit.Type(reflect.TypeOf(float64(0))) ) diff --git a/internal/decoder/jitdec/pools.go b/internal/decoder/jitdec/pools.go index 37b7b7b59..01868cb2f 100644 --- a/internal/decoder/jitdec/pools.go +++ b/internal/decoder/jitdec/pools.go @@ -36,6 +36,7 @@ const ( _PtrBytes = _PTR_SIZE / 8 _FsmOffset = (_MaxStack + 1) * _PtrBytes _DbufOffset = _FsmOffset + int64(unsafe.Sizeof(types.StateMachine{})) + types.MAX_RECURSE * _PtrBytes + _EpOffset = _DbufOffset + _MaxDigitNums _StackSize = unsafe.Sizeof(_Stack{}) ) @@ -53,6 +54,7 @@ type _Stack struct { mm types.StateMachine vp [types.MAX_RECURSE]unsafe.Pointer dp [_MaxDigitNums]byte + ep unsafe.Pointer } type _Decoder func( diff --git a/issue_test/issue692_test.go b/issue_test/issue692_test.go new file mode 100644 index 000000000..39b0010d0 --- /dev/null +++ b/issue_test/issue692_test.go @@ -0,0 +1,47 @@ +// Copyright 2024 CloudWeGo Authors +// +// 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 +// +// https://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 ( + "encoding/json" + "testing" + + "github.com/bytedance/sonic" + "github.com/stretchr/testify/assert" +) + + +type A1 struct { + A *A1 `json:"a"` + B int `json:"b"` + C int `json:"c"` + D D `json:"d"` +} + +type D int + +func (d *D) UnmarshalJSON(data []byte) error { + return nil +} + +func TestMismatchErrorInRecusive(t *testing.T) { + data := `{"a":{"a": null, "b": "123"}, "c": 123, "d": {}}` + var obj1, obj2 A1 + es := sonic.Unmarshal([]byte(data), &obj1) + ee := json.Unmarshal([]byte(data), &obj2) + assert.Equal(t, ee ==nil, es == nil, es) + assert.Equal(t, obj1, obj2) + println(es.Error()) +} \ No newline at end of file diff --git a/loader/loader_latest.go b/loader/loader_latest.go index cc2d7ac00..71431227a 100644 --- a/loader/loader_latest.go +++ b/loader/loader_latest.go @@ -71,7 +71,7 @@ func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize } if localPtrs != nil { - locals := rt .StackMapBuilder{} + locals := rt.StackMapBuilder{} for _, b := range localPtrs { locals.AddField(b) }