1
0
mirror of https://github.com/json-iterator/go.git synced 2025-05-16 21:45:43 +02:00

#133 validate json when Skip()

This commit is contained in:
Tao Wen 2017-07-18 09:45:25 +08:00
parent 5eded4f6ae
commit f6da8e62c3
14 changed files with 88 additions and 44 deletions

View File

@ -259,8 +259,7 @@ func (iter *Iterator) loadMore() bool {
} }
func (iter *Iterator) unreadByte() { func (iter *Iterator) unreadByte() {
if iter.head == 0 { if iter.Error != nil {
iter.ReportError("unreadByte", "unread too many bytes")
return return
} }
iter.head-- iter.head--

View File

@ -88,11 +88,17 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
if !callback(iter, *(*string)(unsafe.Pointer(&field))) { if !callback(iter, *(*string)(unsafe.Pointer(&field))) {
return false return false
} }
for iter.nextToken() == ',' { c = iter.nextToken()
for c == ',' {
field = iter.readObjectFieldAsBytes() field = iter.readObjectFieldAsBytes()
if !callback(iter, *(*string)(unsafe.Pointer(&field))) { if !callback(iter, *(*string)(unsafe.Pointer(&field))) {
return false return false
} }
c = iter.nextToken()
}
if c != '}' {
iter.ReportError("ReadObjectCB", `object not ended with }`)
return false
} }
return true return true
} }
@ -125,7 +131,8 @@ func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
if !callback(iter, field) { if !callback(iter, field) {
return false return false
} }
for iter.nextToken() == ',' { c = iter.nextToken()
for c == ',' {
field = iter.ReadString() field = iter.ReadString()
if iter.nextToken() != ':' { if iter.nextToken() != ':' {
iter.ReportError("ReadMapCB", "expect : after object field") iter.ReportError("ReadMapCB", "expect : after object field")
@ -134,6 +141,11 @@ func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
if !callback(iter, field) { if !callback(iter, field) {
return false return false
} }
c = iter.nextToken()
}
if c != '}' {
iter.ReportError("ReadMapCB", `object not ended with }`)
return false
} }
return true return true
} }

View File

@ -80,9 +80,9 @@ func (iter *Iterator) Skip() {
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
iter.skipNumber() iter.skipNumber()
case '[': case '[':
panic("not implemented") iter.skipArray()
case '{': case '{':
panic("not implemented") iter.skipObject()
default: default:
iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c))
return return

View File

@ -61,7 +61,17 @@ func (iter *Iterator) trySkipString() bool {
} }
func (iter *Iterator) skipObject() { func (iter *Iterator) skipObject() {
iter.unreadByte()
iter.ReadObjectCB(func(iter *Iterator, field string) bool {
iter.Skip()
return true
})
} }
func (iter *Iterator) skipArray() { func (iter *Iterator) skipArray() {
iter.unreadByte()
iter.ReadArrayCB(func(iter *Iterator) bool {
iter.Skip()
return true
})
} }

View File

@ -25,7 +25,6 @@ var stringConvertMap = map[string]string{
"[]": "[]", "[]": "[]",
"[1,2]": "[1,2]", "[1,2]": "[1,2]",
"{}": "{}", "{}": "{}",
"{1,2}": "{1,2}",
`{"a":1, "stream":true}`: `{"a":1, "stream":true}`, `{"a":1, "stream":true}`: `{"a":1, "stream":true}`,
} }

View File

@ -20,11 +20,6 @@ func Test_read_by_one(t *testing.T) {
if iter.Error != nil { if iter.Error != nil {
t.Fatal(iter.Error) t.Fatal(iter.Error)
} }
iter.unreadByte()
if iter.Error == nil {
t.FailNow()
}
iter.Error = nil
b = iter.readByte() b = iter.readByte()
if iter.Error != nil { if iter.Error != nil {
t.Fatal(iter.Error) t.Fatal(iter.Error)

View File

@ -32,6 +32,7 @@ func Test_one_field(t *testing.T) {
iter = ParseString(ConfigDefault, `{"a": "stream"}`) iter = ParseString(ConfigDefault, `{"a": "stream"}`)
should.True(iter.ReadObjectCB(func(iter *Iterator, field string) bool { should.True(iter.ReadObjectCB(func(iter *Iterator, field string) bool {
should.Equal("a", field) should.Equal("a", field)
iter.Skip()
return true return true
})) }))

View File

@ -0,0 +1,12 @@
package test
type typeForTest []interface{}
var inputs = []string{
`[]`, // valid
`[1]`, // valid
`[ 1, "hello"]`, // valid
`[abc]`, // invalid
`[`, // invalid
`[[]`, // invalid
}

View File

@ -0,0 +1 @@
../number/skip_test.go

View File

@ -2,18 +2,18 @@ package test
import ( import (
"encoding/json" "encoding/json"
"errors"
"github.com/json-iterator/go"
"github.com/stretchr/testify/require"
"io" "io"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/json-iterator/go"
"errors"
) )
func Test_skip(t *testing.T) { func Test_skip(t *testing.T) {
for _, input := range inputs { for _, input := range inputs {
t.Run(input, func(t *testing.T) { t.Run(input, func(t *testing.T) {
should := require.New(t) should := require.New(t)
dst := typeForTest(0) var dst typeForTest
stdErr := json.Unmarshal([]byte(input), &dst) stdErr := json.Unmarshal([]byte(input), &dst)
iter := jsoniter.ParseString(jsoniter.ConfigDefault, input) iter := jsoniter.ParseString(jsoniter.ConfigDefault, input)
iter.Skip() iter.Skip()

View File

@ -0,0 +1,16 @@
package test
type typeForTest struct{}
var inputs = []string{
`{}`, // valid
`{"hello":"world"}`, // valid
`{hello:"world"}`, // invalid
`{"hello:"world"}`, // invalid
`{"hello","world"}`, // invalid
`{"hello":{}`, // invalid
`{"hello":{}}`, // valid
`{"hello":{}}}`, // invalid
`{"hello": { "hello": 1}}`, // valid
`{abc}`, // invalid
}

View File

@ -0,0 +1 @@
../number/skip_test.go

View File

@ -27,7 +27,6 @@ func Test_EmptyInput(t *testing.T) {
} }
func Test_RandomInput_Bytes(t *testing.T) { func Test_RandomInput_Bytes(t *testing.T) {
t.Skip("will need to write a safe version of Skip()")
fz := fuzz.New().NilChance(0) fz := fuzz.New().NilChance(0)
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
var jb []byte var jb []byte
@ -37,7 +36,6 @@ func Test_RandomInput_Bytes(t *testing.T) {
} }
func Test_RandomInput_String(t *testing.T) { func Test_RandomInput_String(t *testing.T) {
t.Skip("will need to write a safe version of Skip()")
fz := fuzz.New().NilChance(0) fz := fuzz.New().NilChance(0)
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
var js string var js string