Skip to content

Commit

Permalink
Limit the complexity of "like" queries that match on a pattern.
Browse files Browse the repository at this point in the history
This commit adds the uses the MatchLimit function, which it the
same as Match but will limit the complexity of the input pattern.
This is to avoid long running matches, specifically to avoid ReDos
attacks from arbritary inputs.
  • Loading branch information
tidwall committed Oct 8, 2021
1 parent 590010f commit 77a57fd
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 7 deletions.
17 changes: 13 additions & 4 deletions gjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -1089,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 {
Expand Down Expand Up @@ -1176,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] == '~' {
Expand Down Expand Up @@ -1213,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)
Expand Down
5 changes: 5 additions & 0 deletions gjson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,11 @@ func TestVariousFuzz(t *testing.T) {
testJSON = `[#.@pretty.@join:{""[]""preserve"3,"][{]]]`
Get(testJSON, testJSON)

// Issue #237
testJSON1 := `["*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,"]`
testJSON2 := `#[%"*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,,,,,""*,*"]`
Get(testJSON1, testJSON2)

}

func TestSubpathsWithMultipaths(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ module github.com/tidwall/gjson
go 1.12

require (
github.com/tidwall/match v1.1.0
github.com/tidwall/match v1.1.1
github.com/tidwall/pretty v1.2.0
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
github.com/tidwall/match v1.1.0 h1:VfI2e2aXLvytih7WUVyO9uvRC+RcXlaTrMbHuQWnFmk=
github.com/tidwall/match v1.1.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
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.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=

0 comments on commit 77a57fd

Please sign in to comment.