From 9fe5ece8338b4b53233c2be283801241f570b34f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 13 Jan 2022 14:02:46 -0800 Subject: [PATCH] logtail: cap the buffer size in encodeText This started as an attempt to placate GitHub's code scanner, but it's also probably generally a good idea. Signed-off-by: Josh Bleecher Snyder --- logtail/logtail.go | 29 ++++++++++++++++++++--------- logtail/logtail_test.go | 12 ++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/logtail/logtail.go b/logtail/logtail.go index 4e217bac1..bd30882a5 100644 --- a/logtail/logtail.go +++ b/logtail/logtail.go @@ -431,6 +431,21 @@ func (l *Logger) encodeText(buf []byte, skipClientTime bool) []byte { // For now just factor in a dozen. overhead += 12 + // Put a sanity cap on buf's size. + max := 16 << 10 + if l.lowMem { + max = 255 + } + var nTruncated int + if len(buf) > max { + nTruncated = len(buf) - max + // TODO: this can break a UTF-8 character + // mid-encoding. We don't tend to log + // non-ASCII stuff ourselves, but e.g. client + // names might be. + buf = buf[:max] + } + b := make([]byte, 0, len(buf)+overhead) b = append(b, '{') @@ -449,7 +464,7 @@ func (l *Logger) encodeText(buf []byte, skipClientTime bool) []byte { } b = append(b, "\"text\": \""...) - for i, c := range buf { + for _, c := range buf { switch c { case '\b': b = append(b, '\\', 'b') @@ -469,14 +484,10 @@ func (l *Logger) encodeText(buf []byte, skipClientTime bool) []byte { // TODO: what about binary gibberish or non UTF-8? b = append(b, c) } - if l.lowMem && i > 254 { - // TODO: this can break a UTF-8 character - // mid-encoding. We don't tend to log - // non-ASCII stuff ourselves, but e.g. client - // names might be. - b = append(b, "…"...) - break - } + } + if nTruncated > 0 { + b = append(b, "…+"...) + b = strconv.AppendInt(b, int64(nTruncated), 10) } b = append(b, "\"}\n"...) return b diff --git a/logtail/logtail_test.go b/logtail/logtail_test.go index 7ed193838..cee0d1658 100644 --- a/logtail/logtail_test.go +++ b/logtail/logtail_test.go @@ -5,6 +5,7 @@ package logtail import ( + "bytes" "context" "encoding/json" "io" @@ -323,3 +324,14 @@ func unmarshalOne(t *testing.T, body []byte) map[string]interface{} { } return entries[0] } + +func TestEncodeTextTruncation(t *testing.T) { + lg := &Logger{timeNow: time.Now, lowMem: true} + in := bytes.Repeat([]byte("a"), 300) + b := lg.encodeText(in, true) + got := string(b) + want := `{"text": "` + strings.Repeat("a", 255) + `…+45"}` + "\n" + if got != want { + t.Errorf("got:\n%qwant:\n%q\n", got, want) + } +}