diff options
| author | Shulhan <ms@kilabit.info> | 2021-09-04 00:30:41 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-09-04 00:30:41 +0700 |
| commit | a4c7e73e12157957e12a3f70b42e173b97374eec (patch) | |
| tree | 6031b3670c5a6889261626a3d03abd860b6b7f48 | |
| parent | a5a5e7928bfe3fdca8f74fd28966265efecace0c (diff) | |
| download | pakakeh.go-a4c7e73e12157957e12a3f70b42e173b97374eec.tar.xz | |
os/exec: fix escaped quote inside the same quote
Shell quote is a hell of complex. For example, one can write
shell that execute command that contains quote,
sh -c "psql -c 'CREATE ... IDENTIFIED BY PASSWORD '\''pass'\'''"
or to simplify,
sh -c "psql -c \"CREATE ... IDENTIFIED BY PASSWORD 'pass'\""
| -rw-r--r-- | lib/os/exec/exec.go | 28 | ||||
| -rw-r--r-- | lib/os/exec/exec_test.go | 28 |
2 files changed, 43 insertions, 13 deletions
diff --git a/lib/os/exec/exec.go b/lib/os/exec/exec.go index 0fed245c..1f6f52cf 100644 --- a/lib/os/exec/exec.go +++ b/lib/os/exec/exec.go @@ -32,17 +32,31 @@ func ParseCommandArgs(in string) (cmd string, args []string) { for _, r := range in { if quote > 0 { if r == quote { - arg := sb.String() - if len(arg) > 0 { - cmdArgs = append(cmdArgs, sb.String()) + if prev == '\\' { + sb.WriteRune(r) + prev = r + } else { + arg := sb.String() + if len(arg) > 0 { + cmdArgs = append(cmdArgs, sb.String()) + } + sb.Reset() + quote = 0 + } + } else if r == '\\' { + if prev == '\\' { + sb.WriteRune(r) + prev = 0 + } else { + prev = r } - - sb.Reset() - quote = 0 } else { + if prev == '\\' { + sb.WriteRune('\\') + } sb.WriteRune(r) + prev = r } - prev = r continue } if r == '\'' || r == '"' || r == '`' { diff --git a/lib/os/exec/exec_test.go b/lib/os/exec/exec_test.go index 38e089d0..d0da6e48 100644 --- a/lib/os/exec/exec_test.go +++ b/lib/os/exec/exec_test.go @@ -42,17 +42,33 @@ func TestParseCommandArg(t *testing.T) { expCmd: `a`, expArgs: []string{`b'c`}, }, { - in: `a\ b c\ d`, - expCmd: "a b", + in: `a\ b c\ d`, + expCmd: "a b", expArgs: []string{"c d"}, }, { - in: `a\\ b c\\ d`, - expCmd: `a\`, + in: `a\\ b c\\ d`, + expCmd: `a\`, expArgs: []string{"b", `c\`, "d"}, }, { - in: `a\\\ b c\\\ d`, - expCmd: `a\ b`, + in: `a\\\ b c\\\ d`, + expCmd: `a\ b`, expArgs: []string{`c\ d`}, + }, { + in: `sh -c "echo \"a\""`, + expCmd: "sh", + expArgs: []string{`-c`, `echo "a"`}, + }, { + in: `sh -c "sh -c \"echo 'a\x'\""`, + expCmd: "sh", + expArgs: []string{`-c`, `sh -c "echo 'a\x'"`}, + }, { + in: `sh -c "sh -c \"echo 'a'\'''\""`, + expCmd: "sh", + expArgs: []string{`-c`, `sh -c "echo 'a'\'''"`}, + }, { + in: `sh -c "sh -c \"echo 'a\\\"'\""`, + expCmd: "sh", + expArgs: []string{`-c`, `sh -c "echo 'a\"'"`}, }} for _, c := range cases { |
