From eaa70d4c25a2f1d2b7bcfa7b4bfe750fe30a57f5 Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 16 May 2023 14:13:04 +0800 Subject: [PATCH] fix: initialize the elem when slice grow in decode (#415) * fix: check mismatch error after recusive * fix: initialize the elem when slice grow in decode --------- Co-authored-by: liuqiang Co-authored-by: Yi Duan --- decoder/assembler_amd64_go116.go | 22 ++++++++++++++++++++++ decoder/assembler_amd64_go117.go | 25 ++++++++++++++++++++++++- decoder/decoder_test.go | 30 ++++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/decoder/assembler_amd64_go116.go b/decoder/assembler_amd64_go116.go index fab5d62..f889d86 100644 --- a/decoder/assembler_amd64_go116.go +++ b/decoder/assembler_amd64_go116.go @@ -1661,12 +1661,34 @@ func (self *_Assembler) _asm_OP_slice_append(p *_Instr) { self.WriteRecNotAX(8, _DI, jit.Ptr(_VP, 0), true, true)// MOVQ DI, (VP) self.Emit("MOVQ" , _AX, jit.Ptr(_VP, 8)) // MOVQ AX, 8(VP) self.Emit("MOVQ" , _SI, jit.Ptr(_VP, 16)) // MOVQ SI, 16(VP) + + // because growslice not zero memory {oldcap, newlen} when append et not has ptrdata. + // but we should zero it, avoid decode it as random values. + if rt.UnpackType(p.vt()).PtrData == 0 { + self.Emit("SUBQ" , _AX, _SI) // MOVQ AX, SI + + self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP) + self.Emit("MOVQ" , _DI, _VP) // MOVQ DI, VP + self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX + self.From("MULQ" , _CX) // MULQ CX + self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP + + self.Emit("MOVQ" , _SI, _AX) // MOVQ SI, AX + self.From("MULQ" , _CX) // MULQ CX + self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP) + + self.Emit("MOVQ" , _VP, jit.Ptr(_SP, 0)) // MOVQ VP, (SP) + self.mem_clear_fn(true) // CALL_GO memclr{Has,NoHeap} + self.Sjmp("JMP", "_append_slice_end_{n}") // JMP _append_slice_end_{n} + } + self.Link("_index_{n}") // _index_{n}: self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP) self.Emit("MOVQ" , jit.Ptr(_VP, 0), _VP) // MOVQ (VP), VP self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX self.From("MULQ" , _CX) // MULQ CX self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP + self.Link("_append_slice_end_{n}") } func (self *_Assembler) _asm_OP_object_skip(_ *_Instr) { diff --git a/decoder/assembler_amd64_go117.go b/decoder/assembler_amd64_go117.go index 2862e5d..a952ad2 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 @@ -1646,6 +1646,28 @@ func (self *_Assembler) _asm_OP_slice_append(p *_Instr) { self.WritePtrAX(8, jit.Ptr(_VP, 0), false) // MOVQ AX, (VP) self.Emit("MOVQ" , _BX, jit.Ptr(_VP, 8)) // MOVQ BX, 8(VP) self.Emit("MOVQ" , _CX, jit.Ptr(_VP, 16)) // MOVQ CX, 16(VP) + + // because growslice not zero memory {oldcap, newlen} when append et not has ptrdata. + // but we should zero it, avoid decode it as random values. + if rt.UnpackType(p.vt()).PtrData == 0 { + self.Emit("MOVQ" , _CX, _DI) // MOVQ CX, DI + self.Emit("SUBQ" , _BX, _DI) // MOVQ BX, DI + + self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP) + self.Emit("MOVQ" , _AX, _VP) // MOVQ AX, VP + self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX + self.Emit("MOVQ" , _BX, _AX) // MOVQ BX, AX + self.From("MULQ" , _CX) // MULQ CX + self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP + + self.Emit("MOVQ" , _DI, _AX) // MOVQ SI, AX + self.From("MULQ" , _CX) // MULQ BX + self.Emit("MOVQ" , _AX, _BX) // ADDQ AX, BX + self.Emit("MOVQ" , _VP, _AX) // MOVQ VP, AX + self.mem_clear_fn(true) // CALL_GO memclr{Has,NoHeap} + self.Sjmp("JMP", "_append_slice_end_{n}") + } + self.Emit("MOVQ" , _BX, _AX) // MOVQ BX, AX self.Link("_index_{n}") // _index_{n}: self.Emit("ADDQ" , jit.Imm(1), jit.Ptr(_VP, 8)) // ADDQ $1, 8(VP) @@ -1653,6 +1675,7 @@ func (self *_Assembler) _asm_OP_slice_append(p *_Instr) { self.Emit("MOVQ" , jit.Imm(int64(p.vlen())), _CX) // MOVQ ${p.vlen()}, CX self.From("MULQ" , _CX) // MULQ CX self.Emit("ADDQ" , _AX, _VP) // ADDQ AX, VP + self.Link("_append_slice_end_{n}") } func (self *_Assembler) _asm_OP_object_skip(_ *_Instr) { diff --git a/decoder/decoder_test.go b/decoder/decoder_test.go index afcb9c1..f9c86e2 100644 --- a/decoder/decoder_test.go +++ b/decoder/decoder_test.go @@ -134,9 +134,9 @@ func TestSkipMismatchTypeError(t *testing.T) { t.Fatal("invalid error") } }) - t.Run("array", func(t *testing.T) { + t.Run("short array", func(t *testing.T) { var obj, obj2 = &[]int{}, &[]int{} - var data = `["",1,true]` + var data = `[""]` d := NewDecoder(data) err := d.Decode(obj) err2 := json.Unmarshal([]byte(data), obj2) @@ -145,6 +145,32 @@ func TestSkipMismatchTypeError(t *testing.T) { // assert.Equal(t, len(data), d.i) assert.Equal(t, obj2, obj) }) + + t.Run("int ", func(t *testing.T) { + var obj int = 123 + var obj2 int = 123 + var data = `[""]` + d := NewDecoder(data) + err := d.Decode(&obj) + err2 := json.Unmarshal([]byte(data), &obj2) + println(err.Error(), obj, obj2) + assert.Equal(t, err2 == nil, err == nil) + // assert.Equal(t, len(data), d.i) + assert.Equal(t, obj2, obj) + }) + + t.Run("array", func(t *testing.T) { + var obj, obj2 = &[]int{}, &[]int{} + var data = `["",true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true]` + d := NewDecoder(data) + err := d.Decode(obj) + err2 := json.Unmarshal([]byte(data), obj2) + // println(err2.Error()) + assert.Equal(t, err2 == nil, err == nil) + // assert.Equal(t, len(data), d.i) + assert.Equal(t, obj2, obj) + }) + t.Run("map", func(t *testing.T) { var obj, obj2 = &map[int]int{}, &map[int]int{} var data = `{"true" : { },"1":1,"2" : true,"3":3}`