From 267107b75e8226f3385fc0e085fa45c4b8f47211 Mon Sep 17 00:00:00 2001 From: Jarrod Funnell Date: Tue, 20 Jul 2021 00:16:20 +1000 Subject: [PATCH] Parser: Allow literal control chars in logfmt decoder (#3932) * Allow literal control chars in decoder * Ensure decoding control chars in logfmt works --- pkg/logql/log/logfmt/jsonstring.go | 6 ++-- pkg/logql/log/parser_test.go | 44 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/pkg/logql/log/logfmt/jsonstring.go b/pkg/logql/log/logfmt/jsonstring.go index cd2d76bbe95b..d248280948d9 100644 --- a/pkg/logql/log/logfmt/jsonstring.go +++ b/pkg/logql/log/logfmt/jsonstring.go @@ -36,7 +36,7 @@ func unquoteBytes(s []byte) (t []byte, ok bool) { r := 0 for r < len(s) { c := s[r] - if c == '\\' || c == '"' || c < ' ' { + if c == '\\' || c == '"' { break } if c < utf8.RuneSelf { @@ -118,8 +118,8 @@ func unquoteBytes(s []byte) (t []byte, ok bool) { w += utf8.EncodeRune(b[w:], rr) } - // Quote, control characters are invalid. - case c == '"', c < ' ': + // Unescaped quote is invalid. + case c == '"': return // ASCII diff --git a/pkg/logql/log/parser_test.go b/pkg/logql/log/parser_test.go index 2827335ce3fd..418d8b844104 100644 --- a/pkg/logql/log/parser_test.go +++ b/pkg/logql/log/parser_test.go @@ -603,6 +603,50 @@ func Test_logfmtParser_Parse(t *testing.T) { {Name: "foobar", Value: "foo bar"}, }, }, + { + "escaped control chars in logfmt", + []byte(`foobar="foo\nbar\tbaz"`), + labels.Labels{ + {Name: "a", Value: "b"}, + }, + labels.Labels{ + {Name: "a", Value: "b"}, + {Name: "foobar", Value: "foo\nbar\tbaz"}, + }, + }, + { + "literal control chars in logfmt", + []byte("foobar=\"foo\nbar\tbaz\""), + labels.Labels{ + {Name: "a", Value: "b"}, + }, + labels.Labels{ + {Name: "a", Value: "b"}, + {Name: "foobar", Value: "foo\nbar\tbaz"}, + }, + }, + { + "escaped slash logfmt", + []byte(`foobar="foo ba\\r baz"`), + labels.Labels{ + {Name: "a", Value: "b"}, + }, + labels.Labels{ + {Name: "a", Value: "b"}, + {Name: "foobar", Value: `foo ba\r baz`}, + }, + }, + { + "literal newline and escaped slash logfmt", + []byte("foobar=\"foo bar\nb\\\\az\""), + labels.Labels{ + {Name: "a", Value: "b"}, + }, + labels.Labels{ + {Name: "a", Value: "b"}, + {Name: "foobar", Value: "foo bar\nb\\az"}, + }, + }, { "double property logfmt", []byte(`foobar="foo bar" latency=10ms`),