From f78f8d07f6aca1903611d049bf064c8cea107d9d Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Mon, 24 Apr 2017 19:27:50 +0200 Subject: [PATCH 1/4] Safely format data when printing Fixes #531 --- text_formatter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text_formatter.go b/text_formatter.go index ba88854..8006c0d 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -174,14 +174,14 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { if !f.needsQuoting(value) { b.WriteString(value) } else { - fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter) + fmt.Fprintf(b, "%q", value) } case error: errmsg := value.Error() if !f.needsQuoting(errmsg) { b.WriteString(errmsg) } else { - fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter) + fmt.Fprintf(b, "%q", errmsg) } default: fmt.Fprint(b, value) From 0383f49850e27656e3befd06dfaef6d224a94276 Mon Sep 17 00:00:00 2001 From: Paul Seiffert Date: Mon, 10 Jul 2017 14:09:37 +0200 Subject: [PATCH 2/4] Use custom quote char and escape it --- text_formatter.go | 10 ++++++++-- text_formatter_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/text_formatter.go b/text_formatter.go index 8006c0d..32adbf8 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -174,14 +174,20 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { if !f.needsQuoting(value) { b.WriteString(value) } else { - fmt.Fprintf(b, "%q", value) + escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) + escapedValue := strings.Replace(value, f.QuoteCharacter, escapedQuote, -1) + + fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, escapedValue, f.QuoteCharacter) } case error: errmsg := value.Error() if !f.needsQuoting(errmsg) { b.WriteString(errmsg) } else { - fmt.Fprintf(b, "%q", errmsg) + escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) + escapedErrmsg := strings.Replace(errmsg, f.QuoteCharacter, escapedQuote, -1) + + fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, escapedErrmsg, f.QuoteCharacter) } default: fmt.Fprint(b, value) diff --git a/text_formatter_test.go b/text_formatter_test.go index 9793b5f..f02dc0c 100644 --- a/text_formatter_test.go +++ b/text_formatter_test.go @@ -53,6 +53,48 @@ func TestQuoting(t *testing.T) { checkQuoting(true, errors.New("invalid argument")) } +func TestEscaping_DefaultQuoteCharacter(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + testCases := []struct { + value string + expected string + }{ + {`ba"r`, `ba\"r`}, + {`ba'r`, `ba'r`}, + } + + for _, tc := range testCases { + b, _ := tf.Format(WithField("test", tc.value)) + if !bytes.Contains(b, []byte(tc.expected)) { + t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) + } + } +} + +func TestEscaping_CustomQuoteCharacter(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + testCases := []struct { + value string + expected string + quoteChar string + }{ + {`ba"r`, `ba"r`, `'`}, + {`ba'r`, `ba\'r`, `'`}, + {`ba^r`, `ba\^r`, `^`}, + {`ba'r`, `ba'r`, `^`}, + } + + for _, tc := range testCases { + tf.QuoteCharacter = tc.quoteChar + b, _ := tf.Format(WithField("test", tc.value)) + if !bytes.Contains(b, []byte(tc.expected)) { + t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) + } + } +} + func TestTimestampFormat(t *testing.T) { checkTimeStr := func(format string) { customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format} From 0025402362434acb5a02999b920080debe8bba4f Mon Sep 17 00:00:00 2001 From: Paul Seiffert Date: Mon, 10 Jul 2017 14:17:59 +0200 Subject: [PATCH 3/4] Extract quoting into separate method --- text_formatter.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/text_formatter.go b/text_formatter.go index 32adbf8..26dcc15 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -174,22 +174,23 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { if !f.needsQuoting(value) { b.WriteString(value) } else { - escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) - escapedValue := strings.Replace(value, f.QuoteCharacter, escapedQuote, -1) - - fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, escapedValue, f.QuoteCharacter) + b.WriteString(f.quoteString(value)) } case error: errmsg := value.Error() if !f.needsQuoting(errmsg) { b.WriteString(errmsg) } else { - escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) - escapedErrmsg := strings.Replace(errmsg, f.QuoteCharacter, escapedQuote, -1) - - fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, escapedErrmsg, f.QuoteCharacter) + b.WriteString(f.quoteString(errmsg)) } default: fmt.Fprint(b, value) } } + +func (f *TextFormatter) quoteString(v string) string { + escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) + escapedValue := strings.Replace(v, f.QuoteCharacter, escapedQuote, -1) + + return fmt.Sprintf("%s%v%s", f.QuoteCharacter, escapedValue, f.QuoteCharacter) +} From 04a001ce508c6946033a16224759b3e462a57337 Mon Sep 17 00:00:00 2001 From: Paul Seiffert Date: Mon, 10 Jul 2017 17:40:03 +0200 Subject: [PATCH 4/4] Mention bugfix in changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d415e..6336322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + # 1.0.0 * Officially changed name to lower-case