mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
fix: add nil pointer check (#224)
* fix: add nil pointer check * panicNilPointerOfNonEmptyString
This commit is contained in:
parent
d923a03329
commit
5086cb21fe
4 changed files with 102 additions and 13 deletions
|
|
@ -106,6 +106,7 @@ const (
|
|||
_LB_error_too_deep = "_error_too_deep"
|
||||
_LB_error_invalid_number = "_error_invalid_number"
|
||||
_LB_error_nan_or_infinite = "_error_nan_or_infinite"
|
||||
_LB_panic = "_panic"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -273,6 +274,7 @@ func (self *_Assembler) builtins() {
|
|||
self.error_too_deep()
|
||||
self.error_invalid_number()
|
||||
self.error_nan_or_infinite()
|
||||
self.go_panic()
|
||||
}
|
||||
|
||||
func (self *_Assembler) epilogue() {
|
||||
|
|
@ -625,12 +627,24 @@ func (self *_Assembler) error_nan_or_infinite() {
|
|||
|
||||
var (
|
||||
_F_quote = jit.Imm(int64(native.S_quote))
|
||||
_F_panic = jit.Func(goPanic)
|
||||
)
|
||||
|
||||
func (self *_Assembler) go_panic() {
|
||||
self.Link(_LB_panic)
|
||||
self.Emit("MOVQ", _SP_p, jit.Ptr(_SP, 8))
|
||||
self.call_go(_F_panic)
|
||||
}
|
||||
|
||||
func (self *_Assembler) encode_string(doubleQuote bool) {
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _AX) // MOVQ 8(SP.p), AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JZ" , "_str_empty_{n}") // JZ _str_empty_{n}
|
||||
self.Emit("CMPQ", jit.Ptr(_SP_p, 0), jit.Imm(0))
|
||||
self.Sjmp("JNE" , "_str_next_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), jit.Ptr(_SP, 0))
|
||||
self.Sjmp("JMP", _LB_panic)
|
||||
self.Link("_str_next_{n}")
|
||||
|
||||
/* openning quote, check for double quote */
|
||||
if !doubleQuote {
|
||||
|
|
@ -865,10 +879,15 @@ func (self *_Assembler) _asm_OP_quote(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_number(_ *_Instr) {
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX) // MOVQ (SP.p), AX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _CX) // MOVQ (SP.p), CX
|
||||
self.Emit("TESTQ", _CX, _CX) // TESTQ CX, CX
|
||||
self.Sjmp("JZ" , "_empty_{n}") // JZ _empty_{n}
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX) // MOVQ (SP.p), AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JNZ" , "_number_next_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), jit.Ptr(_SP, 0))
|
||||
self.Sjmp("JMP", _LB_panic)
|
||||
self.Link("_number_next_{n}")
|
||||
self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP)
|
||||
self.Emit("MOVQ" , _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP)
|
||||
self.call_go(_F_isValidNumber) // CALL_GO isValidNumber
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ const (
|
|||
_LB_error_too_deep = "_error_too_deep"
|
||||
_LB_error_invalid_number = "_error_invalid_number"
|
||||
_LB_error_nan_or_infinite = "_error_nan_or_infinite"
|
||||
_LB_panic = "_panic"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -277,6 +278,7 @@ func (self *_Assembler) builtins() {
|
|||
self.error_too_deep()
|
||||
self.error_invalid_number()
|
||||
self.error_nan_or_infinite()
|
||||
self.go_panic()
|
||||
}
|
||||
|
||||
func (self *_Assembler) epilogue() {
|
||||
|
|
@ -636,12 +638,24 @@ func (self *_Assembler) error_nan_or_infinite() {
|
|||
|
||||
var (
|
||||
_F_quote = jit.Imm(int64(native.S_quote))
|
||||
_F_panic = jit.Func(goPanic)
|
||||
)
|
||||
|
||||
func (self *_Assembler) encode_string(doubleQuote bool) {
|
||||
func (self *_Assembler) go_panic() {
|
||||
self.Link(_LB_panic)
|
||||
self.Emit("MOVQ", _SP_p, _BX)
|
||||
self.call_go(_F_panic)
|
||||
}
|
||||
|
||||
func (self *_Assembler) encode_string(doubleQuote bool) {
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _AX) // MOVQ 8(SP.p), AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JZ" , "_str_empty_{n}") // JZ _str_empty_{n}
|
||||
self.Emit("CMPQ", jit.Ptr(_SP_p, 0), jit.Imm(0))
|
||||
self.Sjmp("JNE" , "_str_next_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), _AX)
|
||||
self.Sjmp("JMP", _LB_panic)
|
||||
self.Link("_str_next_{n}")
|
||||
|
||||
/* openning quote, check for double quote */
|
||||
if !doubleQuote {
|
||||
|
|
@ -877,10 +891,15 @@ func (self *_Assembler) _asm_OP_quote(_ *_Instr) {
|
|||
}
|
||||
|
||||
func (self *_Assembler) _asm_OP_number(_ *_Instr) {
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX) // MOVQ (SP.p), AX
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _BX) // MOVQ (SP.p), BX
|
||||
self.Emit("TESTQ", _BX, _BX) // TESTQ BX, BX
|
||||
self.Sjmp("JZ" , "_empty_{n}")
|
||||
self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX) // MOVQ (SP.p), AX
|
||||
self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX
|
||||
self.Sjmp("JNZ" , "_number_next_{n}")
|
||||
self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), _AX)
|
||||
self.Sjmp("JMP", _LB_panic)
|
||||
self.Link("_number_next_{n}")
|
||||
self.call_go(_F_isValidNumber) // CALL_GO isValidNumber
|
||||
self.Emit("CMPB" , _AX, jit.Imm(0)) // CMPB AX, $0
|
||||
self.Sjmp("JE" , _LB_error_invalid_number) // JE _error_invalid_number
|
||||
|
|
|
|||
|
|
@ -17,17 +17,18 @@
|
|||
package encoder
|
||||
|
||||
import (
|
||||
`encoding/hex`
|
||||
`encoding/json`
|
||||
`math`
|
||||
`reflect`
|
||||
`runtime`
|
||||
`testing`
|
||||
`unsafe`
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/stretchr/testify/assert`
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAssembler_CompileAndLoad(t *testing.T) {
|
||||
|
|
@ -375,3 +376,37 @@ func TestAssembler_TwitterJSON_Structure(t *testing.T) {
|
|||
println(string(m))
|
||||
runtime.KeepAlive(s)
|
||||
}
|
||||
|
||||
func TestScratchedString(t *testing.T) {
|
||||
fatal := *(*string)(unsafe.Pointer(&rt.GoString{nil, 1}))
|
||||
defer func(){
|
||||
if v := recover(); v == nil {
|
||||
t.Fatal()
|
||||
} else if s, ok := v.(string); !ok {
|
||||
t.Fatal(v)
|
||||
}else{
|
||||
if !strings.Contains(s, "has nil pointer while its length is not zero") {
|
||||
t.Fatal(s)
|
||||
}
|
||||
}
|
||||
}()
|
||||
_, _ = Encode(fatal, 0)
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
func TestScratchedNumber(t *testing.T) {
|
||||
fatal := *(*json.Number)(unsafe.Pointer(&rt.GoString{nil, 1}))
|
||||
defer func(){
|
||||
if v := recover(); v == nil {
|
||||
t.Fatal()
|
||||
} else if s, ok := v.(string); !ok {
|
||||
t.Fatal(v)
|
||||
}else{
|
||||
if !strings.Contains(s, "has nil pointer while its length is not zero") {
|
||||
t.Fatal(s)
|
||||
}
|
||||
}
|
||||
}()
|
||||
_, _ = Encode(fatal, 0)
|
||||
t.Fatal()
|
||||
}
|
||||
|
|
@ -21,6 +21,9 @@ import (
|
|||
`fmt`
|
||||
`reflect`
|
||||
`strconv`
|
||||
`unsafe`
|
||||
|
||||
`github.com/bytedance/sonic/internal/rt`
|
||||
)
|
||||
|
||||
var _ERR_too_deep = &json.UnsupportedValueError {
|
||||
|
|
@ -47,3 +50,16 @@ func error_number(number json.Number) error {
|
|||
func error_marshaler(ret []byte, pos int) error {
|
||||
return fmt.Errorf("invalid Marshaler output json syntax at %d: %q", pos, ret)
|
||||
}
|
||||
|
||||
const (
|
||||
panicNilPointerOfNonEmptyString int = 1 + iota
|
||||
)
|
||||
|
||||
func goPanic(code int, val unsafe.Pointer) {
|
||||
switch(code){
|
||||
case panicNilPointerOfNonEmptyString:
|
||||
panic(fmt.Sprintf("val: %#v has nil pointer while its length is not zero!", (*rt.GoString)(val)))
|
||||
default:
|
||||
panic("encoder error!")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue