Fix panic: runtime error: index out of range
If the measurement started with a quote, a panic would happen. This
is a reegression due to cb7f0b8
.
This also uncovered that measurement names were being escaped incorrectly.
The escape codes for tag and fields also includes `=` and '"` which should
not be escaped for measurement names.
Fixes #3681
pull/3716/head
parent
4eb48b5a18
commit
329a0cdb74
|
@ -91,6 +91,11 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
escapeCodesStr = map[string]string{}
|
escapeCodesStr = map[string]string{}
|
||||||
|
|
||||||
|
measurementEscapeCodes = map[byte][]byte{
|
||||||
|
',': []byte(`\,`),
|
||||||
|
' ': []byte(`\ `),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -707,7 +712,7 @@ func scanLine(buf []byte, i int) (int, []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we see a double quote, makes sure it is not escaped
|
// If we see a double quote, makes sure it is not escaped
|
||||||
if buf[i] == '"' && buf[i-1] != '\\' {
|
if buf[i] == '"' && (i-1 > 0 && buf[i-1] != '\\') {
|
||||||
i += 1
|
i += 1
|
||||||
quoted = !quoted
|
quoted = !quoted
|
||||||
continue
|
continue
|
||||||
|
@ -827,6 +832,20 @@ func scanFieldValue(buf []byte, i int) (int, []byte) {
|
||||||
return i, buf[start:i]
|
return i, buf[start:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func escapeMeasurement(in []byte) []byte {
|
||||||
|
for b, esc := range measurementEscapeCodes {
|
||||||
|
in = bytes.Replace(in, []byte{b}, esc, -1)
|
||||||
|
}
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
func unescapeMeasurement(in []byte) []byte {
|
||||||
|
for b, esc := range measurementEscapeCodes {
|
||||||
|
in = bytes.Replace(in, esc, []byte{b}, -1)
|
||||||
|
}
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
func escape(in []byte) []byte {
|
func escape(in []byte) []byte {
|
||||||
for b, esc := range escapeCodes {
|
for b, esc := range escapeCodes {
|
||||||
in = bytes.Replace(in, []byte{b}, esc, -1)
|
in = bytes.Replace(in, []byte{b}, esc, -1)
|
||||||
|
@ -948,7 +967,7 @@ func (p *point) Tags() Tags {
|
||||||
func MakeKey(name []byte, tags Tags) []byte {
|
func MakeKey(name []byte, tags Tags) []byte {
|
||||||
// unescape the name and then re-escape it to avoid double escaping.
|
// unescape the name and then re-escape it to avoid double escaping.
|
||||||
// The key should always be stored in escaped form.
|
// The key should always be stored in escaped form.
|
||||||
return append(escape(unescape(name)), tags.HashKey()...)
|
return append(escapeMeasurement(unescapeMeasurement(name)), tags.HashKey()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTags replaces the tags for the point
|
// SetTags replaces the tags for the point
|
||||||
|
|
|
@ -740,7 +740,22 @@ func TestParsePointWithStringWithCommas(t *testing.T) {
|
||||||
},
|
},
|
||||||
time.Unix(1, 0)),
|
time.Unix(1, 0)),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParsePointQuotedMeasurement(t *testing.T) {
|
||||||
|
// non-escaped comma
|
||||||
|
test(t, `"cpu",host=serverA,region=us-east value=1.0 1000000000`,
|
||||||
|
tsdb.NewPoint(
|
||||||
|
`"cpu"`,
|
||||||
|
tsdb.Tags{
|
||||||
|
"host": "serverA",
|
||||||
|
"region": "us-east",
|
||||||
|
},
|
||||||
|
tsdb.Fields{
|
||||||
|
"value": 1.0,
|
||||||
|
},
|
||||||
|
time.Unix(1, 0)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePointEscapedStringsAndCommas(t *testing.T) {
|
func TestParsePointEscapedStringsAndCommas(t *testing.T) {
|
||||||
|
@ -771,7 +786,6 @@ func TestParsePointEscapedStringsAndCommas(t *testing.T) {
|
||||||
},
|
},
|
||||||
time.Unix(1, 0)),
|
time.Unix(1, 0)),
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePointWithStringWithEquals(t *testing.T) {
|
func TestParsePointWithStringWithEquals(t *testing.T) {
|
||||||
|
@ -1193,7 +1207,7 @@ func TestNewPointEscaped(t *testing.T) {
|
||||||
|
|
||||||
// equals
|
// equals
|
||||||
pt = tsdb.NewPoint("cpu=main", tsdb.Tags{"tag=bar": "value=foo"}, tsdb.Fields{"name=bar": 1.0}, time.Unix(0, 0))
|
pt = tsdb.NewPoint("cpu=main", tsdb.Tags{"tag=bar": "value=foo"}, tsdb.Fields{"name=bar": 1.0}, time.Unix(0, 0))
|
||||||
if exp := `cpu\=main,tag\=bar=value\=foo name\=bar=1.0 0`; pt.String() != exp {
|
if exp := `cpu=main,tag\=bar=value\=foo name\=bar=1.0 0`; pt.String() != exp {
|
||||||
t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp)
|
t.Errorf("NewPoint().String() mismatch.\ngot %v\nexp %v", pt.String(), exp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue