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{}
|
||||
|
||||
measurementEscapeCodes = map[byte][]byte{
|
||||
',': []byte(`\,`),
|
||||
' ': []byte(`\ `),
|
||||
}
|
||||
)
|
||||
|
||||
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 buf[i] == '"' && buf[i-1] != '\\' {
|
||||
if buf[i] == '"' && (i-1 > 0 && buf[i-1] != '\\') {
|
||||
i += 1
|
||||
quoted = !quoted
|
||||
continue
|
||||
|
@ -827,6 +832,20 @@ func scanFieldValue(buf []byte, i int) (int, []byte) {
|
|||
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 {
|
||||
for b, esc := range escapeCodes {
|
||||
in = bytes.Replace(in, []byte{b}, esc, -1)
|
||||
|
@ -948,7 +967,7 @@ func (p *point) Tags() Tags {
|
|||
func MakeKey(name []byte, tags Tags) []byte {
|
||||
// unescape the name and then re-escape it to avoid double escaping.
|
||||
// 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
|
||||
|
|
|
@ -740,7 +740,22 @@ func TestParsePointWithStringWithCommas(t *testing.T) {
|
|||
},
|
||||
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) {
|
||||
|
@ -771,7 +786,6 @@ func TestParsePointEscapedStringsAndCommas(t *testing.T) {
|
|||
},
|
||||
time.Unix(1, 0)),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func TestParsePointWithStringWithEquals(t *testing.T) {
|
||||
|
@ -1193,7 +1207,7 @@ func TestNewPointEscaped(t *testing.T) {
|
|||
|
||||
// equals
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue