summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2021-09-04 00:30:41 +0700
committerShulhan <ms@kilabit.info>2021-09-04 00:30:41 +0700
commita4c7e73e12157957e12a3f70b42e173b97374eec (patch)
tree6031b3670c5a6889261626a3d03abd860b6b7f48
parenta5a5e7928bfe3fdca8f74fd28966265efecace0c (diff)
downloadpakakeh.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.go28
-rw-r--r--lib/os/exec/exec_test.go28
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 {