mirror of
https://github.com/ii64/sonic.git
synced 2026-06-20 16:45:22 +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-
|
||||
|
||||
- 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-
|
||||
|
||||
- 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_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||
_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 (
|
||||
|
|
@ -195,6 +195,8 @@ var (
|
|||
_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 {
|
||||
jit.BaseAssembler
|
||||
p _Program
|
||||
|
|
@ -1163,6 +1165,12 @@ func (self *_Assembler) _asm_OP_bool(_ *_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.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
||||
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.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
||||
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) {
|
||||
self.parse_signed() // PARSE 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_fargs = 80 // 80 bytes for passing arguments to other Go functions
|
||||
_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 (
|
||||
|
|
@ -190,6 +190,8 @@ var (
|
|||
_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 {
|
||||
jit.BaseAssembler
|
||||
p _Program
|
||||
|
|
@ -1160,6 +1162,12 @@ func (self *_Assembler) _asm_OP_bool(_ *_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.slice_from(_VAR_st_Ep, 0) // SLICE st.Ep, $0
|
||||
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.Emit("MOVQ", _SI, jit.Ptr(_VP, 8)) // MOVQ SI, 8(VP)
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import (
|
|||
|
||||
func TestMain(m *testing.M) {
|
||||
go func () {
|
||||
if !debugAsyncGC {
|
||||
if debugAsyncGC {
|
||||
return
|
||||
}
|
||||
println("Begin GC looping...")
|
||||
|
|
@ -49,7 +49,7 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func TestGC(t *testing.T) {
|
||||
if debugSyncGC {
|
||||
if !debugSyncGC {
|
||||
return
|
||||
}
|
||||
var w interface{}
|
||||
|
|
|
|||
|
|
@ -56,16 +56,4 @@ 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
|
||||
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(&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