Merge pull request #16530 from influxdata/er-fix-predicate

fix(storage): prevent infinite loop in predicate matcher
pull/16531/head
Edd Robinson 2020-01-14 15:49:38 +00:00 committed by GitHub
commit f3bb6ff042
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 11 deletions

View File

@ -621,17 +621,16 @@ func predicatePopTagEscape(series []byte) (tag, value []byte, rest []byte) {
for j := uint(0); j < uint(len(series)); {
i := bytes.IndexByte(series[j:], ',')
if i < 0 {
break
break // this is the last tag pair
}
ui := uint(i)
if ui > 0 && ui-1 < uint(len(series)) && series[ui-1] == '\\' {
ui := uint(i) + j // make index relative to full series slice
if ui > 0 && series[ui-1] == '\\' { // the comma is escaped
j = ui + 1
continue
}
idx := ui + j
series, rest = series[:idx], series[idx+1:]
series, rest = series[:ui], series[ui+1:]
break
}
@ -639,17 +638,15 @@ func predicatePopTagEscape(series []byte) (tag, value []byte, rest []byte) {
for j := uint(0); j < uint(len(series)); {
i := bytes.IndexByte(series[j:], '=')
if i < 0 {
break
break // there is no tag value
}
ui := uint(i)
if ui > 0 && ui-1 < uint(len(series)) && series[ui-1] == '\\' {
ui := uint(i) + j // make index relative to full series slice
if ui > 0 && series[ui-1] == '\\' { // the equals is escaped
j = ui + 1
continue
}
idx := ui + j
tag, value = series[:idx], series[idx+1:]
tag, value = series[:ui], series[ui+1:]
break
}

View File

@ -8,6 +8,35 @@ import (
"github.com/influxdata/influxdb/storage/reads/datatypes"
)
func TestPredicatePopTagEscape(t *testing.T) {
cases := []struct {
Key string
Tag string
Value string
Rest string
}{
{Key: "", Tag: "", Value: "", Rest: ""},
{Key: "invalid", Tag: "", Value: "", Rest: ""},
{Key: "region=west,server=b,foo=bar", Tag: "region", Value: "west", Rest: "server=b,foo=bar"},
{Key: "region=west", Tag: "region", Value: "west", Rest: ""},
{Key: `re\=gion=west,server=a`, Tag: `re=gion`, Value: "west", Rest: "server=a"},
{Key: `region=w\,est,server=a`, Tag: `region`, Value: "w,est", Rest: "server=a"},
{Key: `hi\ yo\ =w\,est,server=a`, Tag: `hi yo `, Value: "w,est", Rest: "server=a"},
{Key: `\ e\ \=o=world,server=a`, Tag: ` e =o`, Value: "world", Rest: "server=a"},
}
for _, c := range cases {
tag, value, rest := predicatePopTagEscape([]byte(c.Key))
if string(tag) != c.Tag {
t.Fatalf("got returned tag %q expected %q", tag, c.Tag)
} else if string(value) != c.Value {
t.Fatalf("got returned value %q expected %q", value, c.Value)
} else if string(rest) != c.Rest {
t.Fatalf("got returned remainder %q expected %q", rest, c.Rest)
}
}
}
func TestPredicate_Matches(t *testing.T) {
cases := []struct {
Name string