diff --git a/decoder/assembler_amd64.go b/decoder/assembler_amd64.go index 0fac38e..5f689f4 100644 --- a/decoder/assembler_amd64.go +++ b/decoder/assembler_amd64.go @@ -982,6 +982,7 @@ func (self *_Assembler) _asm_OP_any(_ *_Instr) { self.Sjmp("JMP" , "_decode_end_{n}") // JMP _decode_end_{n} self.Link("_decode_{n}") // _decode_{n}: self.Emit("MOVQ" , _ARG_fv, _DF) // MOVQ fv, DF + self.Emit("MOVQ" , _ST, jit.Ptr(_SP, 0)) // MOVQ _ST, (SP) self.call(_F_decodeValue) // CALL decodeValue self.Emit("TESTQ" , _EP, _EP) // TESTQ EP, EP self.Sjmp("JNZ" , _LB_parsing_error) // JNZ _parsing_error diff --git a/decoder/errors_test.go b/decoder/errors_test.go index 3f6d51f..5ab4bed 100644 --- a/decoder/errors_test.go +++ b/decoder/errors_test.go @@ -17,6 +17,7 @@ package decoder import ( + `runtime` `testing` `github.com/bytedance/sonic/internal/native/types` @@ -53,3 +54,15 @@ func TestErrors_ShortDescription(t *testing.T) { func TestErrors_EmptyDescription(t *testing.T) { println(make_err("", 0).Description()) } + +func TestDecoderErrorStackOverflower(t *testing.T) { + src := `{"a":[]}` + N := _MaxStack * runtime.GOMAXPROCS(0) + for i:=0; i _VD_saves / 8 - 1 { panic("too many registers to save") } else { - self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_args + int64(i) * 8)) + self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8)) } } } @@ -87,7 +88,7 @@ func (self *_ValueDecoder) load(r ...obj.Addr) { if i > _VD_saves / 8 - 1 { panic("too many registers to load") } else { - self.Emit("MOVQ", jit.Ptr(_SP, _VD_args + int64(i) * 8), v) + self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v) } } } diff --git a/decoder/pools.go b/decoder/pools.go index 90a622a..b43e8cd 100644 --- a/decoder/pools.go +++ b/decoder/pools.go @@ -64,17 +64,25 @@ var errCallShadow = errors.New("DON'T CALL THIS!") //go:nosplit // Faker func of _Decoder, used to export its stackmap as _Decoder's -func _Decoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) error { +func _Decoder_Shadow(s string, i int, vp unsafe.Pointer, sb *_Stack, fv uint64) (int, error) { // align to assembler_amd64.go: _FP_offs var stacks [_FP_offs]byte runtime.KeepAlive(stacks) - // must keep rb, vp and sb noticeable to GC + // must keep sb noticeable to GC runtime.KeepAlive(sb) - runtime.KeepAlive(rb) - runtime.KeepAlive(vp) + return 0, errCallShadow +} - return errCallShadow +//go:nosplit +// Faker func of _Decoder_Generic, used to export its stackmap +func _Decoder_Generic_Shadow(sb *_Stack) { + // align to generic_amd64.go: _VD_offs + var stacks [_VD_offs]byte + runtime.KeepAlive(stacks) + + // must keep sb noticeable to GC + runtime.KeepAlive(sb) } func newStack() *_Stack { @@ -86,6 +94,7 @@ func newStack() *_Stack { } func freeStack(p *_Stack) { + p.sp = 0 stackPool.Put(p) }