From 6631dd3e12824167076aa72b798c4a60b8d82f18 Mon Sep 17 00:00:00 2001 From: itchyny Date: Mon, 14 Nov 2022 20:27:52 +0900 Subject: [PATCH] escape the null character in csv, tsv, sh formats (close #200) --- cli/test.yaml | 12 ++++++------ func.go | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/cli/test.yaml b/cli/test.yaml index ca303290..c6812dd3 100644 --- a/cli/test.yaml +++ b/cli/test.yaml @@ -5848,9 +5848,9 @@ args: - '@csv' input: | - [1, "foo", null, "foo,\n\"bar\"\tbaz"] + [1, "foo", null, "foo,\n\"bar\"\tbaz\u0000\\0"] expected: | - "1,\"foo\",,\"foo,\n\"\"bar\"\"\tbaz\"" + "1,\"foo\",,\"foo,\n\"\"bar\"\"\tbaz\\0\\0\"" - name: format strings @csv with string interpolation args: @@ -5879,9 +5879,9 @@ args: - '@tsv' input: | - [1, "foo", null, "foo,\n\"bar\"\tba\\z"] + [1, "foo", null, "foo,\n\"bar\"\tbaz\u0000\\0"] expected: | - "1\tfoo\t\tfoo,\\n\"bar\"\\tba\\\\z" + "1\tfoo\t\tfoo,\\n\"bar\"\\tbaz\\0\\\\0" - name: format strings @tsv with string interpolation args: @@ -5912,11 +5912,11 @@ input: | null true - [1, "f'o'o", null, false] + [1, "f'o'o\u0000\\0", null, false] expected: | "null" "true" - "1 'f'\\''o'\\''o' null false" + "1 'f'\\''o'\\''o\\0\\0' null false" - name: format strings @sh error args: diff --git a/func.go b/func.go index d4358ee6..d707bb68 100644 --- a/func.go +++ b/func.go @@ -808,9 +808,14 @@ func funcToURI(v interface{}) interface{} { } } +var csvEscaper = strings.NewReplacer( + `"`, `""`, + "\x00", `\0`, +) + func funcToCSV(v interface{}) interface{} { return formatJoin("csv", v, ",", func(s string) string { - return `"` + strings.ReplaceAll(s, `"`, `""`) + `"` + return `"` + csvEscaper.Replace(s) + `"` }) } @@ -819,18 +824,24 @@ var tsvEscaper = strings.NewReplacer( "\r", `\r`, "\n", `\n`, "\\", `\\`, + "\x00", `\0`, ) func funcToTSV(v interface{}) interface{} { return formatJoin("tsv", v, "\t", tsvEscaper.Replace) } +var shEscaper = strings.NewReplacer( + "'", `'\''`, + "\x00", `\0`, +) + func funcToSh(v interface{}) interface{} { if _, ok := v.([]interface{}); !ok { v = []interface{}{v} } return formatJoin("sh", v, " ", func(s string) string { - return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'" + return "'" + shEscaper.Replace(s) + "'" }) }