Skip to content

Commit c8340d7

Browse files
committed
join: fix unsafe content
1 parent 72dc515 commit c8340d7

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

shlex.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func (t *tokenizer) scanStream() (*Token, error) {
261261
switch nextRuneType {
262262
case eofRuneClass:
263263
switch {
264-
case t.index == 0: // tonkenizer contains an empty string
264+
case t.index == 0: // tokenizer contains an empty string
265265
token.removeLastRaw()
266266
token.Type = WORD_TOKEN
267267
token.Index = t.index
@@ -422,6 +422,8 @@ func Split(s string) (TokenSlice, error) {
422422
// It quotes and escapes where appropriate.
423423
// TODO experimental
424424
func Join(s []string) string {
425+
// TODO how to handle unsafe content? similar to `url.PathEscape` and unsafe by default?
426+
// TODO how to handle home/named directory expansion?
425427
replacer := strings.NewReplacer(
426428
"$", "\\$",
427429
"`", "\\`",
@@ -431,7 +433,7 @@ func Join(s []string) string {
431433
for _, arg := range s {
432434
switch {
433435
case arg == "",
434-
strings.ContainsAny(arg, `"' `+"\n\r\t"):
436+
strings.ContainsAny(arg, `"' `+"`$\n\r\t"): // TODO what about pipeline delimiters
435437
formatted = append(formatted, replacer.Replace(fmt.Sprintf("%#v", arg)))
436438
default:
437439
formatted = append(formatted, arg)

shlex_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,20 @@ func TestSplit(t *testing.T) {
116116
}
117117
}
118118
}
119+
120+
func TestJoin(t *testing.T) {
121+
for expected, words := range map[string][]string{
122+
``: {},
123+
`echo "\$(ls)"`: {"echo", "$(ls)"},
124+
"echo \"\\`ls\\`\"": {"echo", "`ls`"},
125+
"echo \"'ls'\"": {"echo", "'ls'"},
126+
`echo "\"ls\""`: {"echo", `"ls"`},
127+
`echo "\$(ls /tmp)"`: {"echo", "$(ls /tmp)"},
128+
`ls /tmp | xargs -n 1 echo`: {"ls", "/tmp", "|", "xargs", "-n", "1", "echo"},
129+
`echo "one\ntwo"`: {"echo", "one\ntwo"},
130+
} {
131+
if actual := Join(words); actual != expected {
132+
t.Errorf("joined words don't match\nactual : %#v\nexpected: %#v", actual, expected)
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)