mirror of
https://github.com/ii64/sonic.git
synced 2026-06-22 09:26:44 +08:00
fix: allow string value decoded as json.Number (#196)
* fix: allow string value decoded as `json.Number` * test: move -race flag from Go1.15 since it reports "race: limit on 8128 simultaneously alive goroutines is exceeded, dying" * test: add benchmarks
This commit is contained in:
parent
b66168fa77
commit
f087445eee
8 changed files with 95 additions and 19 deletions
2
.github/workflows/push-check-go115.yml
vendored
2
.github/workflows/push-check-go115.yml
vendored
|
|
@ -21,4 +21,4 @@ jobs:
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
- name: Unit Test
|
- name: Unit Test
|
||||||
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -race -covermode=atomic -coverprofile=coverage.out ./...
|
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
|
|
|
||||||
2
.github/workflows/push-check-go116.yml
vendored
2
.github/workflows/push-check-go116.yml
vendored
|
|
@ -21,4 +21,4 @@ jobs:
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
- name: Unit Test
|
- name: Unit Test
|
||||||
run: GOMAXPROCS=4 go test -v -gcflags=-d=checkptr=0 -covermode=atomic -coverprofile=coverage.out ./...
|
run: GOMAXPROCS=4 go test -v -race -gcflags=-d=checkptr=0 -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ const (
|
||||||
_FP_args = 96 // 96 bytes to pass arguments and return values for this function
|
_FP_args = 96 // 96 bytes to pass arguments and return values for this function
|
||||||
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||||
_FP_saves = 40 // 40 bytes for saving the registers before CALL instructions
|
_FP_saves = 40 // 40 bytes for saving the registers before CALL instructions
|
||||||
_FP_locals = 112 // 112 bytes for local variables
|
_FP_locals = 120 // 120 bytes for local variables
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -195,6 +195,8 @@ var (
|
||||||
_VAR_bs_LR = jit.Ptr(_SP, _FP_fargs + _FP_saves + 104)
|
_VAR_bs_LR = jit.Ptr(_SP, _FP_fargs + _FP_saves + 104)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _VAR_fl = jit.Ptr(_SP, _FP_fargs + _FP_saves + 112)
|
||||||
|
|
||||||
type _Assembler struct {
|
type _Assembler struct {
|
||||||
jit.BaseAssembler
|
jit.BaseAssembler
|
||||||
p _Program
|
p _Program
|
||||||
|
|
@ -1163,6 +1165,12 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||||
|
self.Emit("MOVQ", jit.Imm(0), _VAR_fl)
|
||||||
|
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||||
|
self.Sjmp("JNE", "_parse_number_{n}")
|
||||||
|
self.Emit("MOVQ", jit.Imm(1), _VAR_fl)
|
||||||
|
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||||
|
self.Link("_parse_number_{n}")
|
||||||
self.parse_number() // PARSE NUMBER
|
self.parse_number() // PARSE NUMBER
|
||||||
self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
||||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
||||||
|
|
@ -1173,8 +1181,13 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||||
self.Link("_num_write_{n}")
|
self.Link("_num_write_{n}")
|
||||||
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
||||||
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
||||||
|
self.Emit("CMPQ", _VAR_fl, jit.Imm(1))
|
||||||
|
self.Sjmp("JNE", "_num_end_{n}")
|
||||||
|
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||||
|
self.Sjmp("JNE", _LB_char_0_error)
|
||||||
|
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||||
|
self.Link("_num_end_{n}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
||||||
self.parse_signed() // PARSE int8
|
self.parse_signed() // PARSE int8
|
||||||
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
self.range_signed(_I_int8, _T_int8, math.MinInt8, math.MaxInt8) // RANGE int8
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ const (
|
||||||
_FP_args = 72 // 72 bytes to pass and spill register arguements
|
_FP_args = 72 // 72 bytes to pass and spill register arguements
|
||||||
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
_FP_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||||
_FP_saves = 48 // 48 bytes for saving the registers before CALL instructions
|
_FP_saves = 48 // 48 bytes for saving the registers before CALL instructions
|
||||||
_FP_locals = 112 // 112 bytes for local variables
|
_FP_locals = 120 // 112 bytes for local variables
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -190,6 +190,8 @@ var (
|
||||||
_VAR_bs_LR = jit.Ptr(_SP, _FP_fargs + _FP_saves + 104)
|
_VAR_bs_LR = jit.Ptr(_SP, _FP_fargs + _FP_saves + 104)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _VAR_fl = jit.Ptr(_SP, _FP_fargs + _FP_saves + 112)
|
||||||
|
|
||||||
type _Assembler struct {
|
type _Assembler struct {
|
||||||
jit.BaseAssembler
|
jit.BaseAssembler
|
||||||
p _Program
|
p _Program
|
||||||
|
|
@ -1160,6 +1162,12 @@ func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||||
|
self.Emit("MOVQ", jit.Imm(0), _VAR_fl)
|
||||||
|
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||||
|
self.Sjmp("JNE", "_parse_number_{n}")
|
||||||
|
self.Emit("MOVQ", jit.Imm(1), _VAR_fl)
|
||||||
|
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||||
|
self.Link("_parse_number_{n}")
|
||||||
self.parse_number() // PARSE NUMBER
|
self.parse_number() // PARSE NUMBER
|
||||||
self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
self.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
||||||
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
self.Emit("BTQ", jit.Imm(_F_copy_string), _ARG_fv)
|
||||||
|
|
@ -1170,6 +1178,12 @@ func (self *_Assembler) _asm_OP_num(_ *_Instr) {
|
||||||
self.Link("_num_write_{n}")
|
self.Link("_num_write_{n}")
|
||||||
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
self.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
||||||
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
self.WriteRecNotAX(13, _DI, jit.Ptr(_VP, 0), false, false)
|
||||||
|
self.Emit("CMPQ", _VAR_fl, jit.Imm(1))
|
||||||
|
self.Sjmp("JNE", "_num_end_{n}")
|
||||||
|
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm('"'))
|
||||||
|
self.Sjmp("JNE", _LB_char_0_error)
|
||||||
|
self.Emit("ADDQ", jit.Imm(1), _IC)
|
||||||
|
self.Link("_num_end_{n}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import (
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
go func () {
|
go func () {
|
||||||
if !debugAsyncGC {
|
if debugAsyncGC {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println("Begin GC looping...")
|
println("Begin GC looping...")
|
||||||
|
|
@ -49,7 +49,7 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGC(t *testing.T) {
|
func TestGC(t *testing.T) {
|
||||||
if debugSyncGC {
|
if !debugSyncGC {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var w interface{}
|
var w interface{}
|
||||||
|
|
|
||||||
|
|
@ -56,16 +56,4 @@ func TestErrors_ShortDescription(t *testing.T) {
|
||||||
|
|
||||||
func TestErrors_EmptyDescription(t *testing.T) {
|
func TestErrors_EmptyDescription(t *testing.T) {
|
||||||
println(make_err("", 0).Description())
|
println(make_err("", 0).Description())
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecoderErrorStackOverflower(t *testing.T) {
|
|
||||||
src := `{"a":[]}`
|
|
||||||
N := _MaxStack
|
|
||||||
for i:=0; i<N; i++ {
|
|
||||||
var obj map[string]string
|
|
||||||
err := NewDecoder(src).Decode(&obj)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -79,4 +79,16 @@ func TestStringReferring(t *testing.T) {
|
||||||
|
|
||||||
runtime.KeepAlive(&obj)
|
runtime.KeepAlive(&obj)
|
||||||
runtime.KeepAlive(&obj2)
|
runtime.KeepAlive(&obj2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecoderErrorStackOverflower(t *testing.T) {
|
||||||
|
src := `{"a":[]}`
|
||||||
|
N := _MaxStack
|
||||||
|
for i:=0; i<N; i++ {
|
||||||
|
var obj map[string]string
|
||||||
|
err := NewDecoder(src).Decode(&obj)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
49
issue_test/issue195_test.go
Normal file
49
issue_test/issue195_test.go
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 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`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeStringToJsonNumber(t *testing.T) {
|
||||||
|
var objs json.Number
|
||||||
|
errs := sonic.UnmarshalString(`"1234"`, &objs)
|
||||||
|
var obje json.Number
|
||||||
|
erre := json.Unmarshal([]byte(`"1234"`), &obje)
|
||||||
|
require.Equal(t, erre, errs)
|
||||||
|
require.Equal(t, obje, objs)
|
||||||
|
|
||||||
|
errs = sonic.UnmarshalString(`"12x4"`, &objs)
|
||||||
|
erre = json.Unmarshal([]byte(`"12x4"`), &obje)
|
||||||
|
require.Error(t, errs)
|
||||||
|
require.Error(t, erre)
|
||||||
|
|
||||||
|
errs = sonic.UnmarshalString(`"1234`, &objs)
|
||||||
|
erre = json.Unmarshal([]byte(`"1234`), &obje)
|
||||||
|
require.Error(t, errs)
|
||||||
|
require.Error(t, erre)
|
||||||
|
|
||||||
|
errs = sonic.UnmarshalString(`1234"`, &objs)
|
||||||
|
erre = json.Unmarshal([]byte(`1234"`), &obje)
|
||||||
|
require.Error(t, errs)
|
||||||
|
require.Error(t, erre)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue