mirror of https://github.com/stashapp/stash.git
Bump github.com/tidwall/gjson from 1.8.1 to 1.9.3 (#1906)
Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.8.1 to 1.9.3. - [Release notes](https://github.com/tidwall/gjson/releases) - [Commits](https://github.com/tidwall/gjson/compare/v1.8.1...v1.9.3) --- updated-dependencies: - dependency-name: github.com/tidwall/gjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
0dbee117d8
commit
32db1dda57
6
go.mod
6
go.mod
|
@ -32,9 +32,8 @@ require (
|
|||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/tidwall/gjson v1.8.1
|
||||
github.com/tidwall/gjson v1.9.3
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.0.1
|
||||
github.com/vektra/mockery/v2 v2.2.1
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
||||
|
@ -83,9 +82,10 @@ require (
|
|||
github.com/spf13/jwalterweatherman v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tidwall/match v1.0.3 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/urfave/cli/v2 v2.1.1 // indirect
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.0.1 // indirect
|
||||
go.uber.org/atomic v1.6.0 // indirect
|
||||
golang.org/x/mod v0.4.1 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
|
|
9
go.sum
9
go.sum
|
@ -652,12 +652,11 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
|
|||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU=
|
||||
github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E=
|
||||
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
|
|
|
@ -123,11 +123,12 @@ nil, for JSON null
|
|||
To directly access the value:
|
||||
|
||||
```go
|
||||
result.Type // can be String, Number, True, False, Null, or JSON
|
||||
result.Str // holds the string
|
||||
result.Num // holds the float64 number
|
||||
result.Raw // holds the raw json
|
||||
result.Index // index of raw value in original json, zero means index unknown
|
||||
result.Type // can be String, Number, True, False, Null, or JSON
|
||||
result.Str // holds the string
|
||||
result.Num // holds the float64 number
|
||||
result.Raw // holds the raw json
|
||||
result.Index // index of raw value in original json, zero means index unknown
|
||||
result.Indexes // indexes of all the elements that match on a path containing the '#' query character.
|
||||
```
|
||||
|
||||
There are a variety of handy functions that work on a result:
|
||||
|
|
|
@ -291,8 +291,8 @@ gjson.AddModifier("case", func(json, arg string) string {
|
|||
### Multipaths
|
||||
|
||||
Starting with v1.3.0, GJSON added the ability to join multiple paths together
|
||||
to form new documents. Wrapping comma-separated paths between `{...}` or
|
||||
`[...]` will result in a new array or object, respectively.
|
||||
to form new documents. Wrapping comma-separated paths between `[...]` or
|
||||
`{...}` will result in a new array or object, respectively.
|
||||
|
||||
For example, using the given multipath
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@ type Result struct {
|
|||
Num float64
|
||||
// Index of raw value in original json, zero means index unknown
|
||||
Index int
|
||||
// Indexes of all the elements that match on a path containing the '#'
|
||||
// query character.
|
||||
Indexes []int
|
||||
}
|
||||
|
||||
// String returns a string representation of the value.
|
||||
|
@ -281,7 +284,8 @@ func (t Result) ForEach(iterator func(key, value Result) bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// Map returns back an map of values. The result should be a JSON array.
|
||||
// Map returns back a map of values. The result should be a JSON object.
|
||||
// If the result is not a JSON object, the return value will be an empty map.
|
||||
func (t Result) Map() map[string]Result {
|
||||
if t.Type != JSON {
|
||||
return map[string]Result{}
|
||||
|
@ -1085,9 +1089,9 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
|||
}
|
||||
if rp.wild {
|
||||
if kesc {
|
||||
pmatch = match.Match(unescape(key), rp.part)
|
||||
pmatch = matchLimit(unescape(key), rp.part)
|
||||
} else {
|
||||
pmatch = match.Match(key, rp.part)
|
||||
pmatch = matchLimit(key, rp.part)
|
||||
}
|
||||
} else {
|
||||
if kesc {
|
||||
|
@ -1172,6 +1176,15 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
|||
}
|
||||
return i, false
|
||||
}
|
||||
|
||||
// matchLimit will limit the complexity of the match operation to avoid ReDos
|
||||
// attacks from arbritary inputs.
|
||||
// See the github.com/tidwall/match.MatchLimit function for more information.
|
||||
func matchLimit(str, pattern string) bool {
|
||||
matched, _ := match.MatchLimit(str, pattern, 10000)
|
||||
return matched
|
||||
}
|
||||
|
||||
func queryMatches(rp *arrayPathResult, value Result) bool {
|
||||
rpv := rp.query.value
|
||||
if len(rpv) > 0 && rpv[0] == '~' {
|
||||
|
@ -1209,9 +1222,9 @@ func queryMatches(rp *arrayPathResult, value Result) bool {
|
|||
case ">=":
|
||||
return value.Str >= rpv
|
||||
case "%":
|
||||
return match.Match(value.Str, rpv)
|
||||
return matchLimit(value.Str, rpv)
|
||||
case "!%":
|
||||
return !match.Match(value.Str, rpv)
|
||||
return !matchLimit(value.Str, rpv)
|
||||
}
|
||||
case Number:
|
||||
rpvn, _ := strconv.ParseFloat(rpv, 64)
|
||||
|
@ -1261,6 +1274,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
var alog []int
|
||||
var partidx int
|
||||
var multires []byte
|
||||
var queryIndexes []int
|
||||
rp := parseArrayPath(path)
|
||||
if !rp.arrch {
|
||||
n, ok := parseUint(rp.part)
|
||||
|
@ -1281,6 +1295,10 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
multires = append(multires, '[')
|
||||
}
|
||||
}
|
||||
var tmp parseContext
|
||||
tmp.value = qval
|
||||
fillIndex(c.json, &tmp)
|
||||
parentIndex := tmp.value.Index
|
||||
var res Result
|
||||
if qval.Type == JSON {
|
||||
res = qval.Get(rp.query.path)
|
||||
|
@ -1312,6 +1330,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
multires = append(multires, ',')
|
||||
}
|
||||
multires = append(multires, raw...)
|
||||
queryIndexes = append(queryIndexes, res.Index+parentIndex)
|
||||
}
|
||||
} else {
|
||||
c.value = res
|
||||
|
@ -1476,6 +1495,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
c.pipe = right
|
||||
c.piped = true
|
||||
}
|
||||
var indexes = make([]int, 0, 64)
|
||||
var jsons = make([]byte, 0, 64)
|
||||
jsons = append(jsons, '[')
|
||||
for j, k := 0, 0; j < len(alog); j++ {
|
||||
|
@ -1490,6 +1510,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
}
|
||||
if idx < len(c.json) && c.json[idx] != ']' {
|
||||
_, res, ok := parseAny(c.json, idx, true)
|
||||
parentIndex := res.Index
|
||||
if ok {
|
||||
res := res.Get(rp.alogkey)
|
||||
if res.Exists() {
|
||||
|
@ -1501,6 +1522,8 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
raw = res.String()
|
||||
}
|
||||
jsons = append(jsons, []byte(raw)...)
|
||||
indexes = append(indexes,
|
||||
res.Index+parentIndex)
|
||||
k++
|
||||
}
|
||||
}
|
||||
|
@ -1509,6 +1532,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
jsons = append(jsons, ']')
|
||||
c.value.Type = JSON
|
||||
c.value.Raw = string(jsons)
|
||||
c.value.Indexes = indexes
|
||||
return i + 1, true
|
||||
}
|
||||
if rp.alogok {
|
||||
|
@ -1524,8 +1548,9 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
|||
if !c.value.Exists() {
|
||||
if len(multires) > 0 {
|
||||
c.value = Result{
|
||||
Raw: string(append(multires, ']')),
|
||||
Type: JSON,
|
||||
Raw: string(append(multires, ']')),
|
||||
Type: JSON,
|
||||
Indexes: queryIndexes,
|
||||
}
|
||||
} else if rp.query.all {
|
||||
c.value = Result{
|
||||
|
@ -1806,6 +1831,7 @@ func Get(json, path string) Result {
|
|||
if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
|
||||
res := Get(rjson, path[1:])
|
||||
res.Index = 0
|
||||
res.Indexes = nil
|
||||
return res
|
||||
}
|
||||
return Parse(rjson)
|
||||
|
@ -2046,7 +2072,10 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
|
|||
res.Raw = val
|
||||
res.Type = JSON
|
||||
}
|
||||
return i, res, true
|
||||
var tmp parseContext
|
||||
tmp.value = res
|
||||
fillIndex(json, &tmp)
|
||||
return i, tmp.value, true
|
||||
}
|
||||
if json[i] <= ' ' {
|
||||
continue
|
||||
|
@ -2455,7 +2484,8 @@ func parseInt(s string) (n int64, ok bool) {
|
|||
// safeInt validates a given JSON number
|
||||
// ensures it lies within the minimum and maximum representable JSON numbers
|
||||
func safeInt(f float64) (n int64, ok bool) {
|
||||
// https://tc39.es/ecma262/#sec-number.min_safe_integer || https://tc39.es/ecma262/#sec-number.max_safe_integer
|
||||
// https://tc39.es/ecma262/#sec-number.min_safe_integer
|
||||
// https://tc39.es/ecma262/#sec-number.max_safe_integer
|
||||
if f < -9007199254740991 || f > 9007199254740991 {
|
||||
return 0, false
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Package match provides a simple pattern matcher with unicode support.
|
||||
package match
|
||||
|
||||
import "unicode/utf8"
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Match returns true if str matches pattern. This is a very
|
||||
// simple wildcard match where '*' matches on any number characters
|
||||
|
@ -16,127 +18,170 @@ import "unicode/utf8"
|
|||
// '\\' c matches character c
|
||||
//
|
||||
func Match(str, pattern string) bool {
|
||||
return deepMatch(str, pattern)
|
||||
}
|
||||
|
||||
func deepMatch(str, pattern string) bool {
|
||||
if pattern == "*" {
|
||||
return true
|
||||
}
|
||||
for len(pattern) > 1 && pattern[0] == '*' && pattern[1] == '*' {
|
||||
pattern = pattern[1:]
|
||||
}
|
||||
for len(pattern) > 0 {
|
||||
if pattern[0] > 0x7f {
|
||||
return deepMatchRune(str, pattern)
|
||||
}
|
||||
switch pattern[0] {
|
||||
default:
|
||||
if len(str) == 0 {
|
||||
return false
|
||||
}
|
||||
if str[0] > 0x7f {
|
||||
return deepMatchRune(str, pattern)
|
||||
}
|
||||
if str[0] != pattern[0] {
|
||||
return false
|
||||
}
|
||||
case '?':
|
||||
if len(str) == 0 {
|
||||
return false
|
||||
}
|
||||
case '*':
|
||||
return deepMatch(str, pattern[1:]) ||
|
||||
(len(str) > 0 && deepMatch(str[1:], pattern))
|
||||
}
|
||||
str = str[1:]
|
||||
pattern = pattern[1:]
|
||||
}
|
||||
return len(str) == 0 && len(pattern) == 0
|
||||
return match(str, pattern, 0, nil, -1) == rMatch
|
||||
}
|
||||
|
||||
func deepMatchRune(str, pattern string) bool {
|
||||
// MatchLimit is the same as Match but will limit the complexity of the match
|
||||
// operation. This is to avoid long running matches, specifically to avoid ReDos
|
||||
// attacks from arbritary inputs.
|
||||
//
|
||||
// How it works:
|
||||
// The underlying match routine is recursive and may call itself when it
|
||||
// encounters a sandwiched wildcard pattern, such as: `user:*:name`.
|
||||
// Everytime it calls itself a counter is incremented.
|
||||
// The operation is stopped when counter > maxcomp*len(str).
|
||||
func MatchLimit(str, pattern string, maxcomp int) (matched, stopped bool) {
|
||||
if pattern == "*" {
|
||||
return true
|
||||
return true, false
|
||||
}
|
||||
for len(pattern) > 1 && pattern[0] == '*' && pattern[1] == '*' {
|
||||
pattern = pattern[1:]
|
||||
counter := 0
|
||||
r := match(str, pattern, len(str), &counter, maxcomp)
|
||||
if r == rStop {
|
||||
return false, true
|
||||
}
|
||||
return r == rMatch, false
|
||||
}
|
||||
|
||||
type result int
|
||||
|
||||
const (
|
||||
rNoMatch result = iota
|
||||
rMatch
|
||||
rStop
|
||||
)
|
||||
|
||||
func match(str, pat string, slen int, counter *int, maxcomp int) result {
|
||||
// check complexity limit
|
||||
if maxcomp > -1 {
|
||||
if *counter > slen*maxcomp {
|
||||
return rStop
|
||||
}
|
||||
*counter++
|
||||
}
|
||||
|
||||
var sr, pr rune
|
||||
var srsz, prsz int
|
||||
|
||||
// read the first rune ahead of time
|
||||
if len(str) > 0 {
|
||||
if str[0] > 0x7f {
|
||||
sr, srsz = utf8.DecodeRuneInString(str)
|
||||
} else {
|
||||
sr, srsz = rune(str[0]), 1
|
||||
for len(pat) > 0 {
|
||||
var wild bool
|
||||
pc, ps := rune(pat[0]), 1
|
||||
if pc > 0x7f {
|
||||
pc, ps = utf8.DecodeRuneInString(pat)
|
||||
}
|
||||
} else {
|
||||
sr, srsz = utf8.RuneError, 0
|
||||
}
|
||||
if len(pattern) > 0 {
|
||||
if pattern[0] > 0x7f {
|
||||
pr, prsz = utf8.DecodeRuneInString(pattern)
|
||||
} else {
|
||||
pr, prsz = rune(pattern[0]), 1
|
||||
}
|
||||
} else {
|
||||
pr, prsz = utf8.RuneError, 0
|
||||
}
|
||||
// done reading
|
||||
for pr != utf8.RuneError {
|
||||
switch pr {
|
||||
default:
|
||||
if srsz == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
if sr != pr {
|
||||
return false
|
||||
}
|
||||
case '?':
|
||||
if srsz == utf8.RuneError {
|
||||
return false
|
||||
}
|
||||
case '*':
|
||||
return deepMatchRune(str, pattern[prsz:]) ||
|
||||
(srsz > 0 && deepMatchRune(str[srsz:], pattern))
|
||||
}
|
||||
str = str[srsz:]
|
||||
pattern = pattern[prsz:]
|
||||
// read the next runes
|
||||
var sc rune
|
||||
var ss int
|
||||
if len(str) > 0 {
|
||||
if str[0] > 0x7f {
|
||||
sr, srsz = utf8.DecodeRuneInString(str)
|
||||
} else {
|
||||
sr, srsz = rune(str[0]), 1
|
||||
sc, ss = rune(str[0]), 1
|
||||
if sc > 0x7f {
|
||||
sc, ss = utf8.DecodeRuneInString(str)
|
||||
}
|
||||
} else {
|
||||
sr, srsz = utf8.RuneError, 0
|
||||
}
|
||||
if len(pattern) > 0 {
|
||||
if pattern[0] > 0x7f {
|
||||
pr, prsz = utf8.DecodeRuneInString(pattern)
|
||||
} else {
|
||||
pr, prsz = rune(pattern[0]), 1
|
||||
switch pc {
|
||||
case '?':
|
||||
if ss == 0 {
|
||||
return rNoMatch
|
||||
}
|
||||
case '*':
|
||||
// Ignore repeating stars.
|
||||
for len(pat) > 1 && pat[1] == '*' {
|
||||
pat = pat[1:]
|
||||
}
|
||||
} else {
|
||||
pr, prsz = utf8.RuneError, 0
|
||||
}
|
||||
// done reading
|
||||
}
|
||||
|
||||
return srsz == 0 && prsz == 0
|
||||
// If this star is the last character then it must be a match.
|
||||
if len(pat) == 1 {
|
||||
return rMatch
|
||||
}
|
||||
|
||||
// Match and trim any non-wildcard suffix characters.
|
||||
var ok bool
|
||||
str, pat, ok = matchTrimSuffix(str, pat)
|
||||
if !ok {
|
||||
return rNoMatch
|
||||
}
|
||||
|
||||
// Check for single star again.
|
||||
if len(pat) == 1 {
|
||||
return rMatch
|
||||
}
|
||||
|
||||
// Perform recursive wildcard search.
|
||||
r := match(str, pat[1:], slen, counter, maxcomp)
|
||||
if r != rNoMatch {
|
||||
return r
|
||||
}
|
||||
if len(str) == 0 {
|
||||
return rNoMatch
|
||||
}
|
||||
wild = true
|
||||
default:
|
||||
if ss == 0 {
|
||||
return rNoMatch
|
||||
}
|
||||
if pc == '\\' {
|
||||
pat = pat[ps:]
|
||||
pc, ps = utf8.DecodeRuneInString(pat)
|
||||
if ps == 0 {
|
||||
return rNoMatch
|
||||
}
|
||||
}
|
||||
if sc != pc {
|
||||
return rNoMatch
|
||||
}
|
||||
}
|
||||
str = str[ss:]
|
||||
if !wild {
|
||||
pat = pat[ps:]
|
||||
}
|
||||
}
|
||||
if len(str) == 0 {
|
||||
return rMatch
|
||||
}
|
||||
return rNoMatch
|
||||
}
|
||||
|
||||
var maxRuneBytes = func() []byte {
|
||||
b := make([]byte, 4)
|
||||
if utf8.EncodeRune(b, '\U0010FFFF') != 4 {
|
||||
panic("invalid rune encoding")
|
||||
// matchTrimSuffix matches and trims any non-wildcard suffix characters.
|
||||
// Returns the trimed string and pattern.
|
||||
//
|
||||
// This is called because the pattern contains extra data after the wildcard
|
||||
// star. Here we compare any suffix characters in the pattern to the suffix of
|
||||
// the target string. Basically a reverse match that stops when a wildcard
|
||||
// character is reached. This is a little trickier than a forward match because
|
||||
// we need to evaluate an escaped character in reverse.
|
||||
//
|
||||
// Any matched characters will be trimmed from both the target
|
||||
// string and the pattern.
|
||||
func matchTrimSuffix(str, pat string) (string, string, bool) {
|
||||
// It's expected that the pattern has at least two bytes and the first byte
|
||||
// is a wildcard star '*'
|
||||
match := true
|
||||
for len(str) > 0 && len(pat) > 1 {
|
||||
pc, ps := utf8.DecodeLastRuneInString(pat)
|
||||
var esc bool
|
||||
for i := 0; ; i++ {
|
||||
if pat[len(pat)-ps-i-1] != '\\' {
|
||||
if i&1 == 1 {
|
||||
esc = true
|
||||
ps++
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if pc == '*' && !esc {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
sc, ss := utf8.DecodeLastRuneInString(str)
|
||||
if !((pc == '?' && !esc) || pc == sc) {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
str = str[:len(str)-ss]
|
||||
pat = pat[:len(pat)-ps]
|
||||
}
|
||||
return b
|
||||
}()
|
||||
return str, pat, match
|
||||
}
|
||||
|
||||
var maxRuneBytes = [...]byte{244, 143, 191, 191}
|
||||
|
||||
// Allowable parses the pattern and determines the minimum and maximum allowable
|
||||
// values that the pattern can represent.
|
||||
|
@ -157,7 +202,7 @@ func Allowable(pattern string) (min, max string) {
|
|||
}
|
||||
if pattern[i] == '?' {
|
||||
minb = append(minb, 0)
|
||||
maxb = append(maxb, maxRuneBytes...)
|
||||
maxb = append(maxb, maxRuneBytes[:]...)
|
||||
} else {
|
||||
minb = append(minb, pattern[i])
|
||||
maxb = append(maxb, pattern[i])
|
||||
|
|
|
@ -322,10 +322,10 @@ github.com/stretchr/testify/mock
|
|||
# github.com/subosito/gotenv v1.2.0
|
||||
## explicit
|
||||
github.com/subosito/gotenv
|
||||
# github.com/tidwall/gjson v1.8.1
|
||||
# github.com/tidwall/gjson v1.9.3
|
||||
## explicit; go 1.12
|
||||
github.com/tidwall/gjson
|
||||
# github.com/tidwall/match v1.0.3
|
||||
# github.com/tidwall/match v1.1.1
|
||||
## explicit; go 1.15
|
||||
github.com/tidwall/match
|
||||
# github.com/tidwall/pretty v1.2.0
|
||||
|
|
Loading…
Reference in New Issue