2
0
Fork 0
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:
Yi Duan 2022-02-28 20:14:38 +08:00 committed by GitHub
parent b66168fa77
commit f087445eee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 19 deletions

View file

@ -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 ./...

View file

@ -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 ./...

View file

@ -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

View file

@ -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) {

View file

@ -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{}

View file

@ -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)
}
}
}

View file

@ -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)
}
}
}

View 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)
}