go.mod: github.com/buger/jsonparser v1.1.1
Fix CVE-2020-35381 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
2
go.mod
2
go.mod
@ -5,7 +5,7 @@ go 1.14
|
|||||||
require (
|
require (
|
||||||
github.com/Microsoft/hcsshim v0.8.16
|
github.com/Microsoft/hcsshim v0.8.16
|
||||||
github.com/alexflint/go-filemutex v1.1.0
|
github.com/alexflint/go-filemutex v1.1.0
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
github.com/buger/jsonparser v1.1.1
|
||||||
github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a
|
github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a
|
||||||
github.com/coreos/go-iptables v0.5.0
|
github.com/coreos/go-iptables v0.5.0
|
||||||
github.com/coreos/go-systemd/v22 v22.2.0
|
github.com/coreos/go-systemd/v22 v22.2.0
|
||||||
|
3
go.sum
3
go.sum
@ -76,8 +76,9 @@ github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
|
|||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 h1:y853v6rXx+zefEcjET3JuKAqvhj+FKflQijjeaSv2iA=
|
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
|
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||||
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||||
|
2
vendor/github.com/buger/jsonparser/.gitignore
generated
vendored
2
vendor/github.com/buger/jsonparser/.gitignore
generated
vendored
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
*.mprof
|
*.mprof
|
||||||
|
|
||||||
|
.idea
|
||||||
|
|
||||||
vendor/github.com/buger/goterm/
|
vendor/github.com/buger/goterm/
|
||||||
prof.cpu
|
prof.cpu
|
||||||
prof.mem
|
prof.mem
|
||||||
|
10
vendor/github.com/buger/jsonparser/.travis.yml
generated
vendored
10
vendor/github.com/buger/jsonparser/.travis.yml
generated
vendored
@ -1,3 +1,11 @@
|
|||||||
language: go
|
language: go
|
||||||
go: 1.7
|
arch:
|
||||||
|
- amd64
|
||||||
|
- ppc64le
|
||||||
|
go:
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
script: go test -v ./.
|
script: go test -v ./.
|
||||||
|
4
vendor/github.com/buger/jsonparser/README.md
generated
vendored
4
vendor/github.com/buger/jsonparser/README.md
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
[](https://goreportcard.com/report/github.com/buger/jsonparser) 
|
[](https://goreportcard.com/report/github.com/buger/jsonparser) 
|
||||||
# Alternative JSON parser for Go (so far fastest)
|
# Alternative JSON parser for Go (10x times faster standard library)
|
||||||
|
|
||||||
It does not require you to know the structure of the payload (eg. create structs), and allows accessing fields by providing the path to them. It is up to **10 times faster** than standard `encoding/json` package (depending on payload size and usage), **allocates no memory**. See benchmarks below.
|
It does not require you to know the structure of the payload (eg. create structs), and allows accessing fields by providing the path to them. It is up to **10 times faster** than standard `encoding/json` package (depending on payload size and usage), **allocates no memory**. See benchmarks below.
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, off
|
|||||||
}, "person", "avatars")
|
}, "person", "avatars")
|
||||||
|
|
||||||
// Or use can access fields by index!
|
// Or use can access fields by index!
|
||||||
jsonparser.GetInt("person", "avatars", "[0]", "url")
|
jsonparser.GetString(data, "person", "avatars", "[0]", "url")
|
||||||
|
|
||||||
// You can use `ObjectEach` helper to iterate objects { "key1":object1, "key2":object2, .... "keyN":objectN }
|
// You can use `ObjectEach` helper to iterate objects { "key1":object1, "key2":object2, .... "keyN":objectN }
|
||||||
jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
|
jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
|
||||||
|
33
vendor/github.com/buger/jsonparser/bytes.go
generated
vendored
33
vendor/github.com/buger/jsonparser/bytes.go
generated
vendored
@ -1,9 +1,16 @@
|
|||||||
package jsonparser
|
package jsonparser
|
||||||
|
|
||||||
// About 3x faster then strconv.ParseInt because does not check for range error and support only base 10, which is enough for JSON
|
import (
|
||||||
func parseInt(bytes []byte) (v int64, ok bool) {
|
bio "bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// minInt64 '-9223372036854775808' is the smallest representable number in int64
|
||||||
|
const minInt64 = `9223372036854775808`
|
||||||
|
|
||||||
|
// About 2x faster then strconv.ParseInt because it only supports base 10, which is enough for JSON
|
||||||
|
func parseInt(bytes []byte) (v int64, ok bool, overflow bool) {
|
||||||
if len(bytes) == 0 {
|
if len(bytes) == 0 {
|
||||||
return 0, false
|
return 0, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var neg bool = false
|
var neg bool = false
|
||||||
@ -12,17 +19,29 @@ func parseInt(bytes []byte) (v int64, ok bool) {
|
|||||||
bytes = bytes[1:]
|
bytes = bytes[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var b int64 = 0
|
||||||
for _, c := range bytes {
|
for _, c := range bytes {
|
||||||
if c >= '0' && c <= '9' {
|
if c >= '0' && c <= '9' {
|
||||||
v = (10 * v) + int64(c-'0')
|
b = (10 * v) + int64(c-'0')
|
||||||
} else {
|
} else {
|
||||||
return 0, false
|
return 0, false, false
|
||||||
}
|
}
|
||||||
|
if overflow = (b < v); overflow {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v = b
|
||||||
|
}
|
||||||
|
|
||||||
|
if overflow {
|
||||||
|
if neg && bio.Equal(bytes, []byte(minInt64)) {
|
||||||
|
return b, true, false
|
||||||
|
}
|
||||||
|
return 0, false, true
|
||||||
}
|
}
|
||||||
|
|
||||||
if neg {
|
if neg {
|
||||||
return -v, true
|
return -v, true, false
|
||||||
} else {
|
} else {
|
||||||
return v, true
|
return v, true, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/buger/jsonparser/bytes_unsafe.go
generated
vendored
14
vendor/github.com/buger/jsonparser/bytes_unsafe.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -32,11 +33,12 @@ func bytesToString(b *[]byte) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StringToBytes(s string) []byte {
|
func StringToBytes(s string) []byte {
|
||||||
|
b := make([]byte, 0, 0)
|
||||||
|
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||||
bh := reflect.SliceHeader{
|
bh.Data = sh.Data
|
||||||
Data: sh.Data,
|
bh.Cap = sh.Len
|
||||||
Len: sh.Len,
|
bh.Len = sh.Len
|
||||||
Cap: sh.Len,
|
runtime.KeepAlive(s)
|
||||||
}
|
return b
|
||||||
return *(*[]byte)(unsafe.Pointer(&bh))
|
|
||||||
}
|
}
|
||||||
|
117
vendor/github.com/buger/jsonparser/fuzz.go
generated
vendored
Normal file
117
vendor/github.com/buger/jsonparser/fuzz.go
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package jsonparser
|
||||||
|
|
||||||
|
func FuzzParseString(data []byte) int {
|
||||||
|
r, err := ParseString(data)
|
||||||
|
if err != nil || r == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzEachKey(data []byte) int {
|
||||||
|
paths := [][]string{
|
||||||
|
{"name"},
|
||||||
|
{"order"},
|
||||||
|
{"nested", "a"},
|
||||||
|
{"nested", "b"},
|
||||||
|
{"nested2", "a"},
|
||||||
|
{"nested", "nested3", "b"},
|
||||||
|
{"arr", "[1]", "b"},
|
||||||
|
{"arrInt", "[3]"},
|
||||||
|
{"arrInt", "[5]"},
|
||||||
|
{"nested"},
|
||||||
|
{"arr", "["},
|
||||||
|
{"a\n", "b\n"},
|
||||||
|
}
|
||||||
|
EachKey(data, func(idx int, value []byte, vt ValueType, err error) {}, paths...)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzDelete(data []byte) int {
|
||||||
|
Delete(data, "test")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzSet(data []byte) int {
|
||||||
|
_, err := Set(data, []byte(`"new value"`), "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzObjectEach(data []byte) int {
|
||||||
|
_ = ObjectEach(data, func(key, value []byte, valueType ValueType, off int) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzParseFloat(data []byte) int {
|
||||||
|
_, err := ParseFloat(data)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzParseInt(data []byte) int {
|
||||||
|
_, err := ParseInt(data)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzParseBool(data []byte) int {
|
||||||
|
_, err := ParseBoolean(data)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzTokenStart(data []byte) int {
|
||||||
|
_ = tokenStart(data)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetString(data []byte) int {
|
||||||
|
_, err := GetString(data, "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetFloat(data []byte) int {
|
||||||
|
_, err := GetFloat(data, "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetInt(data []byte) int {
|
||||||
|
_, err := GetInt(data, "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetBoolean(data []byte) int {
|
||||||
|
_, err := GetBoolean(data, "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetUnsafeString(data []byte) int {
|
||||||
|
_, err := GetUnsafeString(data, "test")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
4
vendor/github.com/buger/jsonparser/go.mod
generated
vendored
Normal file
4
vendor/github.com/buger/jsonparser/go.mod
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module github.com/buger/jsonparser
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
0
vendor/github.com/buger/jsonparser/go.sum
generated
vendored
Normal file
0
vendor/github.com/buger/jsonparser/go.sum
generated
vendored
Normal file
47
vendor/github.com/buger/jsonparser/oss-fuzz-build.sh
generated
vendored
Normal file
47
vendor/github.com/buger/jsonparser/oss-fuzz-build.sh
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
git clone https://github.com/dvyukov/go-fuzz-corpus
|
||||||
|
zip corpus.zip go-fuzz-corpus/json/corpus/*
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzparsestring_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzParseString fuzzparsestring
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzeachkey_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzEachKey fuzzeachkey
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzdelete_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzDelete fuzzdelete
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzset_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzSet fuzzset
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzobjecteach_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzObjectEach fuzzobjecteach
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzparsefloat_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzParseFloat fuzzparsefloat
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzparseint_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzParseInt fuzzparseint
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzparsebool_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzParseBool fuzzparsebool
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzztokenstart_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzTokenStart fuzztokenstart
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzgetstring_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzGetString fuzzgetstring
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzgetfloat_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzGetFloat fuzzgetfloat
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzgetint_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzGetInt fuzzgetint
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzgetboolean_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzGetBoolean fuzzgetboolean
|
||||||
|
|
||||||
|
cp corpus.zip $OUT/fuzzgetunsafestring_seed_corpus.zip
|
||||||
|
compile_go_fuzzer github.com/buger/jsonparser FuzzGetUnsafeString fuzzgetunsafestring
|
||||||
|
|
234
vendor/github.com/buger/jsonparser/parser.go
generated
vendored
234
vendor/github.com/buger/jsonparser/parser.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,6 +16,7 @@ var (
|
|||||||
MalformedArrayError = errors.New("Value is array, but can't find closing ']' symbol")
|
MalformedArrayError = errors.New("Value is array, but can't find closing ']' symbol")
|
||||||
MalformedObjectError = errors.New("Value looks like object, but can't find closing '}' symbol")
|
MalformedObjectError = errors.New("Value looks like object, but can't find closing '}' symbol")
|
||||||
MalformedValueError = errors.New("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol")
|
MalformedValueError = errors.New("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol")
|
||||||
|
OverflowIntegerError = errors.New("Value is number, but overflowed while parsing")
|
||||||
MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
|
MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -97,9 +97,15 @@ func findKeyStart(data []byte, key string) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
i = blockEnd(data[i:], data[i], ']') + i
|
end := blockEnd(data[i:], data[i], ']')
|
||||||
|
if end != -1 {
|
||||||
|
i = i + end
|
||||||
|
}
|
||||||
case '{':
|
case '{':
|
||||||
i = blockEnd(data[i:], data[i], '}') + i
|
end := blockEnd(data[i:], data[i], '}')
|
||||||
|
if end != -1 {
|
||||||
|
i = i + end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -213,6 +219,7 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
i := 0
|
i := 0
|
||||||
ln := len(data)
|
ln := len(data)
|
||||||
lk := len(keys)
|
lk := len(keys)
|
||||||
|
lastMatched := true
|
||||||
|
|
||||||
if lk == 0 {
|
if lk == 0 {
|
||||||
return 0
|
return 0
|
||||||
@ -240,8 +247,8 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
|
|
||||||
i += valueOffset
|
i += valueOffset
|
||||||
|
|
||||||
// if string is a key, and key level match
|
// if string is a key
|
||||||
if data[i] == ':' && keyLevel == level-1 {
|
if data[i] == ':' {
|
||||||
if level < 1 {
|
if level < 1 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -259,18 +266,40 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
keyUnesc = ku
|
keyUnesc = ku
|
||||||
}
|
}
|
||||||
|
|
||||||
if equalStr(&keyUnesc, keys[level-1]) {
|
if level <= len(keys) {
|
||||||
keyLevel++
|
if equalStr(&keyUnesc, keys[level-1]) {
|
||||||
// If we found all keys in path
|
lastMatched = true
|
||||||
if keyLevel == lk {
|
|
||||||
return i + 1
|
// if key level match
|
||||||
|
if keyLevel == level-1 {
|
||||||
|
keyLevel++
|
||||||
|
// If we found all keys in path
|
||||||
|
if keyLevel == lk {
|
||||||
|
return i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lastMatched = false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i--
|
i--
|
||||||
}
|
}
|
||||||
case '{':
|
case '{':
|
||||||
level++
|
|
||||||
|
// in case parent key is matched then only we will increase the level otherwise can directly
|
||||||
|
// can move to the end of this block
|
||||||
|
if !lastMatched {
|
||||||
|
end := blockEnd(data[i:], '{', '}')
|
||||||
|
if end == -1 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
i += end - 1
|
||||||
|
} else {
|
||||||
|
level++
|
||||||
|
}
|
||||||
case '}':
|
case '}':
|
||||||
level--
|
level--
|
||||||
if level == keyLevel {
|
if level == keyLevel {
|
||||||
@ -279,7 +308,11 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
case '[':
|
case '[':
|
||||||
// If we want to get array element by index
|
// If we want to get array element by index
|
||||||
if keyLevel == level && keys[level][0] == '[' {
|
if keyLevel == level && keys[level][0] == '[' {
|
||||||
aIdx, err := strconv.Atoi(keys[level][1 : len(keys[level])-1])
|
var keyLen = len(keys[level])
|
||||||
|
if keyLen < 3 || keys[level][0] != '[' || keys[level][keyLen-1] != ']' {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
aIdx, err := strconv.Atoi(keys[level][1 : keyLen-1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -316,6 +349,8 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
i += arraySkip - 1
|
i += arraySkip - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case ':': // If encountered, JSON data is malformed
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
i++
|
||||||
@ -324,14 +359,6 @@ func searchKeys(data []byte, keys ...string) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
var bitwiseFlags []int64
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for i := 0; i < 63; i++ {
|
|
||||||
bitwiseFlags = append(bitwiseFlags, int64(math.Pow(2, float64(i))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sameTree(p1, p2 []string) bool {
|
func sameTree(p1, p2 []string) bool {
|
||||||
minLen := len(p1)
|
minLen := len(p1)
|
||||||
if len(p2) < minLen {
|
if len(p2) < minLen {
|
||||||
@ -348,7 +375,8 @@ func sameTree(p1, p2 []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string) int {
|
func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string) int {
|
||||||
var pathFlags int64
|
var x struct{}
|
||||||
|
pathFlags := make([]bool, len(paths))
|
||||||
var level, pathsMatched, i int
|
var level, pathsMatched, i int
|
||||||
ln := len(data)
|
ln := len(data)
|
||||||
|
|
||||||
@ -359,7 +387,6 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var stackbuf [unescapeStackBufSize]byte // stack-allocated array for allocation-free unescaping of small strings
|
|
||||||
pathsBuf := make([]string, maxPath)
|
pathsBuf := make([]string, maxPath)
|
||||||
|
|
||||||
for i < ln {
|
for i < ln {
|
||||||
@ -393,10 +420,13 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
|
|||||||
var keyUnesc []byte
|
var keyUnesc []byte
|
||||||
if !keyEscaped {
|
if !keyEscaped {
|
||||||
keyUnesc = key
|
keyUnesc = key
|
||||||
} else if ku, err := Unescape(key, stackbuf[:]); err != nil {
|
|
||||||
return -1
|
|
||||||
} else {
|
} else {
|
||||||
keyUnesc = ku
|
var stackbuf [unescapeStackBufSize]byte
|
||||||
|
if ku, err := Unescape(key, stackbuf[:]); err != nil {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
keyUnesc = ku
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxPath >= level {
|
if maxPath >= level {
|
||||||
@ -407,23 +437,18 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
|
|||||||
|
|
||||||
pathsBuf[level-1] = bytesToString(&keyUnesc)
|
pathsBuf[level-1] = bytesToString(&keyUnesc)
|
||||||
for pi, p := range paths {
|
for pi, p := range paths {
|
||||||
if len(p) != level || pathFlags&bitwiseFlags[pi+1] != 0 || !equalStr(&keyUnesc, p[level-1]) || !sameTree(p, pathsBuf[:level]) {
|
if len(p) != level || pathFlags[pi] || !equalStr(&keyUnesc, p[level-1]) || !sameTree(p, pathsBuf[:level]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
match = pi
|
match = pi
|
||||||
|
|
||||||
i++
|
|
||||||
pathsMatched++
|
pathsMatched++
|
||||||
pathFlags |= bitwiseFlags[pi+1]
|
pathFlags[pi] = true
|
||||||
|
|
||||||
v, dt, of, e := Get(data[i:])
|
v, dt, _, e := Get(data[i+1:])
|
||||||
cb(pi, v, dt, e)
|
cb(pi, v, dt, e)
|
||||||
|
|
||||||
if of != -1 {
|
|
||||||
i += of
|
|
||||||
}
|
|
||||||
|
|
||||||
if pathsMatched == len(paths) {
|
if pathsMatched == len(paths) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -457,8 +482,9 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
|
|||||||
case '}':
|
case '}':
|
||||||
level--
|
level--
|
||||||
case '[':
|
case '[':
|
||||||
var arrIdxFlags int64
|
var ok bool
|
||||||
var pIdxFlags int64
|
arrIdxFlags := make(map[int]struct{})
|
||||||
|
pIdxFlags := make([]bool, len(paths))
|
||||||
|
|
||||||
if level < 0 {
|
if level < 0 {
|
||||||
cb(-1, nil, Unknown, MalformedJsonError)
|
cb(-1, nil, Unknown, MalformedJsonError)
|
||||||
@ -466,30 +492,31 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
|
|||||||
}
|
}
|
||||||
|
|
||||||
for pi, p := range paths {
|
for pi, p := range paths {
|
||||||
if len(p) < level+1 || pathFlags&bitwiseFlags[pi+1] != 0 || p[level][0] != '[' || !sameTree(p, pathsBuf[:level]) {
|
if len(p) < level+1 || pathFlags[pi] || p[level][0] != '[' || !sameTree(p, pathsBuf[:level]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if len(p[level]) >= 2 {
|
||||||
aIdx, _ := strconv.Atoi(p[level][1 : len(p[level])-1])
|
aIdx, _ := strconv.Atoi(p[level][1 : len(p[level])-1])
|
||||||
arrIdxFlags |= bitwiseFlags[aIdx+1]
|
arrIdxFlags[aIdx] = x
|
||||||
pIdxFlags |= bitwiseFlags[pi+1]
|
pIdxFlags[pi] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if arrIdxFlags > 0 {
|
if len(arrIdxFlags) > 0 {
|
||||||
level++
|
level++
|
||||||
|
|
||||||
var curIdx int
|
var curIdx int
|
||||||
arrOff, _ := ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
|
arrOff, _ := ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
|
||||||
if arrIdxFlags&bitwiseFlags[curIdx+1] != 0 {
|
if _, ok = arrIdxFlags[curIdx]; ok {
|
||||||
for pi, p := range paths {
|
for pi, p := range paths {
|
||||||
if pIdxFlags&bitwiseFlags[pi+1] != 0 {
|
if pIdxFlags[pi] {
|
||||||
aIdx, _ := strconv.Atoi(p[level-1][1 : len(p[level-1])-1])
|
aIdx, _ := strconv.Atoi(p[level-1][1 : len(p[level-1])-1])
|
||||||
|
|
||||||
if curIdx == aIdx {
|
if curIdx == aIdx {
|
||||||
of := searchKeys(value, p[level:]...)
|
of := searchKeys(value, p[level:]...)
|
||||||
|
|
||||||
pathsMatched++
|
pathsMatched++
|
||||||
pathFlags |= bitwiseFlags[pi+1]
|
pathFlags[pi] = true
|
||||||
|
|
||||||
if of != -1 {
|
if of != -1 {
|
||||||
v, dt, _, e := Get(value[of:])
|
v, dt, _, e := Get(value[of:])
|
||||||
@ -568,46 +595,96 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func createInsertComponent(keys []string, setValue []byte, comma, object bool) []byte {
|
func createInsertComponent(keys []string, setValue []byte, comma, object bool) []byte {
|
||||||
var buffer bytes.Buffer
|
|
||||||
isIndex := string(keys[0][0]) == "["
|
isIndex := string(keys[0][0]) == "["
|
||||||
|
offset := 0
|
||||||
|
lk := calcAllocateSpace(keys, setValue, comma, object)
|
||||||
|
buffer := make([]byte, lk, lk)
|
||||||
if comma {
|
if comma {
|
||||||
buffer.WriteString(",")
|
offset += WriteToBuffer(buffer[offset:], ",")
|
||||||
}
|
}
|
||||||
if isIndex {
|
if isIndex && !comma {
|
||||||
buffer.WriteString("[")
|
offset += WriteToBuffer(buffer[offset:], "[")
|
||||||
} else {
|
} else {
|
||||||
if object {
|
if object {
|
||||||
buffer.WriteString("{")
|
offset += WriteToBuffer(buffer[offset:], "{")
|
||||||
|
}
|
||||||
|
if !isIndex {
|
||||||
|
offset += WriteToBuffer(buffer[offset:], "\"")
|
||||||
|
offset += WriteToBuffer(buffer[offset:], keys[0])
|
||||||
|
offset += WriteToBuffer(buffer[offset:], "\":")
|
||||||
}
|
}
|
||||||
buffer.WriteString("\"")
|
|
||||||
buffer.WriteString(keys[0])
|
|
||||||
buffer.WriteString("\":")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 1; i < len(keys); i++ {
|
for i := 1; i < len(keys); i++ {
|
||||||
if string(keys[i][0]) == "[" {
|
if string(keys[i][0]) == "[" {
|
||||||
buffer.WriteString("[")
|
offset += WriteToBuffer(buffer[offset:], "[")
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString("{\"")
|
offset += WriteToBuffer(buffer[offset:], "{\"")
|
||||||
buffer.WriteString(keys[i])
|
offset += WriteToBuffer(buffer[offset:], keys[i])
|
||||||
buffer.WriteString("\":")
|
offset += WriteToBuffer(buffer[offset:], "\":")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.Write(setValue)
|
offset += WriteToBuffer(buffer[offset:], string(setValue))
|
||||||
for i := len(keys) - 1; i > 0; i-- {
|
for i := len(keys) - 1; i > 0; i-- {
|
||||||
if string(keys[i][0]) == "[" {
|
if string(keys[i][0]) == "[" {
|
||||||
buffer.WriteString("]")
|
offset += WriteToBuffer(buffer[offset:], "]")
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteString("}")
|
offset += WriteToBuffer(buffer[offset:], "}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isIndex {
|
if isIndex && !comma {
|
||||||
buffer.WriteString("]")
|
offset += WriteToBuffer(buffer[offset:], "]")
|
||||||
}
|
}
|
||||||
if object && !isIndex {
|
if object && !isIndex {
|
||||||
buffer.WriteString("}")
|
offset += WriteToBuffer(buffer[offset:], "}")
|
||||||
}
|
}
|
||||||
return buffer.Bytes()
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcAllocateSpace(keys []string, setValue []byte, comma, object bool) int {
|
||||||
|
isIndex := string(keys[0][0]) == "["
|
||||||
|
lk := 0
|
||||||
|
if comma {
|
||||||
|
// ,
|
||||||
|
lk += 1
|
||||||
|
}
|
||||||
|
if isIndex && !comma {
|
||||||
|
// []
|
||||||
|
lk += 2
|
||||||
|
} else {
|
||||||
|
if object {
|
||||||
|
// {
|
||||||
|
lk += 1
|
||||||
|
}
|
||||||
|
if !isIndex {
|
||||||
|
// "keys[0]"
|
||||||
|
lk += len(keys[0]) + 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lk += len(setValue)
|
||||||
|
for i := 1; i < len(keys); i++ {
|
||||||
|
if string(keys[i][0]) == "[" {
|
||||||
|
// []
|
||||||
|
lk += 2
|
||||||
|
} else {
|
||||||
|
// {"keys[i]":setValue}
|
||||||
|
lk += len(keys[i]) + 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if object && !isIndex {
|
||||||
|
// }
|
||||||
|
lk += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return lk
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteToBuffer(buffer []byte, str string) int {
|
||||||
|
copy(buffer, str)
|
||||||
|
return len(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -687,7 +764,12 @@ func Delete(data []byte, keys ...string) []byte {
|
|||||||
newOffset = prevTok + 1
|
newOffset = prevTok + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
data = append(data[:newOffset], data[endOffset:]...)
|
// We have to make a copy here if we don't want to mangle the original data, because byte slices are
|
||||||
|
// accessed by reference and not by value
|
||||||
|
dataCopy := make([]byte, len(data))
|
||||||
|
copy(dataCopy, data)
|
||||||
|
data = append(dataCopy[:newOffset], dataCopy[endOffset:]...)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +812,7 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
|
|||||||
if endOffset == -1 {
|
if endOffset == -1 {
|
||||||
firstToken := nextToken(data)
|
firstToken := nextToken(data)
|
||||||
// We can't set a top-level key if data isn't an object
|
// We can't set a top-level key if data isn't an object
|
||||||
if len(data) == 0 || data[firstToken] != '{' {
|
if firstToken < 0 || data[firstToken] != '{' {
|
||||||
return nil, KeyPathNotFoundError
|
return nil, KeyPathNotFoundError
|
||||||
}
|
}
|
||||||
// Don't need a comma if the input is an empty object
|
// Don't need a comma if the input is an empty object
|
||||||
@ -745,7 +827,9 @@ func Set(data []byte, setValue []byte, keys ...string) (value []byte, err error)
|
|||||||
depthOffset := endOffset
|
depthOffset := endOffset
|
||||||
if depth != 0 {
|
if depth != 0 {
|
||||||
// if subpath is a non-empty object, add to it
|
// if subpath is a non-empty object, add to it
|
||||||
if data[startOffset] == '{' && data[startOffset+1+nextToken(data[startOffset+1:])] != '}' {
|
// or if subpath is a non-empty array, add to it
|
||||||
|
if (data[startOffset] == '{' && data[startOffset+1+nextToken(data[startOffset+1:])] != '}') ||
|
||||||
|
(data[startOffset] == '[' && data[startOffset+1+nextToken(data[startOffset+1:])] == '{') && keys[depth:][0][0] == 91 {
|
||||||
depthOffset--
|
depthOffset--
|
||||||
startOffset = depthOffset
|
startOffset = depthOffset
|
||||||
// otherwise, over-write it with a new object
|
// otherwise, over-write it with a new object
|
||||||
@ -878,7 +962,7 @@ func internalGet(data []byte, keys ...string) (value []byte, dataType ValueType,
|
|||||||
value = value[1 : len(value)-1]
|
value = value[1 : len(value)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, dataType, offset, endOffset, nil
|
return value[:len(value):len(value)], dataType, offset, endOffset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayEach is used when iterating arrays, accepts a callback function with the same return arguments as `Get`.
|
// ArrayEach is used when iterating arrays, accepts a callback function with the same return arguments as `Get`.
|
||||||
@ -887,7 +971,12 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int
|
|||||||
return -1, MalformedObjectError
|
return -1, MalformedObjectError
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = 1
|
nT := nextToken(data)
|
||||||
|
if nT == -1 {
|
||||||
|
return -1, MalformedJsonError
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = nT + 1
|
||||||
|
|
||||||
if len(keys) > 0 {
|
if len(keys) > 0 {
|
||||||
if offset = searchKeys(data, keys...); offset == -1 {
|
if offset = searchKeys(data, keys...); offset == -1 {
|
||||||
@ -963,7 +1052,6 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int
|
|||||||
|
|
||||||
// ObjectEach iterates over the key-value pairs of a JSON object, invoking a given callback for each such entry
|
// ObjectEach iterates over the key-value pairs of a JSON object, invoking a given callback for each such entry
|
||||||
func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) {
|
func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType, offset int) error, keys ...string) (err error) {
|
||||||
var stackbuf [unescapeStackBufSize]byte // stack-allocated array for allocation-free unescaping of small strings
|
|
||||||
offset := 0
|
offset := 0
|
||||||
|
|
||||||
// Descend to the desired key, if requested
|
// Descend to the desired key, if requested
|
||||||
@ -1017,6 +1105,7 @@ func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType Va
|
|||||||
|
|
||||||
// Unescape the string if needed
|
// Unescape the string if needed
|
||||||
if keyEscaped {
|
if keyEscaped {
|
||||||
|
var stackbuf [unescapeStackBufSize]byte // stack-allocated array for allocation-free unescaping of small strings
|
||||||
if keyUnescaped, err := Unescape(key, stackbuf[:]); err != nil {
|
if keyUnescaped, err := Unescape(key, stackbuf[:]); err != nil {
|
||||||
return MalformedStringEscapeError
|
return MalformedStringEscapeError
|
||||||
} else {
|
} else {
|
||||||
@ -1092,7 +1181,7 @@ func GetString(data []byte, keys ...string) (val string, err error) {
|
|||||||
return "", fmt.Errorf("Value is not a string: %s", string(v))
|
return "", fmt.Errorf("Value is not a string: %s", string(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no escapes return raw conten
|
// If no escapes return raw content
|
||||||
if bytes.IndexByte(v, '\\') == -1 {
|
if bytes.IndexByte(v, '\\') == -1 {
|
||||||
return string(v), nil
|
return string(v), nil
|
||||||
}
|
}
|
||||||
@ -1183,7 +1272,10 @@ func ParseFloat(b []byte) (float64, error) {
|
|||||||
|
|
||||||
// ParseInt parses a Number ValueType into a Go int64
|
// ParseInt parses a Number ValueType into a Go int64
|
||||||
func ParseInt(b []byte) (int64, error) {
|
func ParseInt(b []byte) (int64, error) {
|
||||||
if v, ok := parseInt(b); !ok {
|
if v, ok, overflow := parseInt(b); !ok {
|
||||||
|
if overflow {
|
||||||
|
return 0, OverflowIntegerError
|
||||||
|
}
|
||||||
return 0, MalformedValueError
|
return 0, MalformedValueError
|
||||||
} else {
|
} else {
|
||||||
return v, nil
|
return v, nil
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -32,7 +32,7 @@ github.com/Microsoft/hcsshim/osversion
|
|||||||
# github.com/alexflint/go-filemutex v1.1.0
|
# github.com/alexflint/go-filemutex v1.1.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/alexflint/go-filemutex
|
github.com/alexflint/go-filemutex
|
||||||
# github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
# github.com/buger/jsonparser v1.1.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/buger/jsonparser
|
github.com/buger/jsonparser
|
||||||
# github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68
|
# github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68
|
||||||
|
Reference in New Issue
Block a user