diff options
| author | Ron Yorston <rmy@pobox.com> | 2016-03-16 10:38:37 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2016-03-16 10:38:37 +0000 |
| commit | 037cdc9c020ae6875a0707aeab5f7ecceef7e351 (patch) | |
| tree | f2602e6f3a17c8164a7b4e45d75bc44f4a87b21e | |
| parent | 2762242f30d0d046a80abe41fd78415052bbe95f (diff) | |
| download | busybox-w32-037cdc9c020ae6875a0707aeab5f7ecceef7e351.tar.gz busybox-w32-037cdc9c020ae6875a0707aeab5f7ecceef7e351.tar.bz2 busybox-w32-037cdc9c020ae6875a0707aeab5f7ecceef7e351.zip | |
win32: fix quoting of arguments with trailing backslashes
Correctly handle the case where an argument needs to be quoted
and has a backslash as its last character.
The issue was detected by the test "sed a cmd ended by double backslash"
in the BusyBox test suite.
| -rw-r--r-- | win32/process.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/win32/process.c b/win32/process.c index 2206a0a5e..951519e59 100644 --- a/win32/process.c +++ b/win32/process.c | |||
| @@ -119,58 +119,91 @@ parse_interpreter(const char *cmd, char ***opts, int *nopts) | |||
| 119 | static char * | 119 | static char * |
| 120 | quote_arg(const char *arg) | 120 | quote_arg(const char *arg) |
| 121 | { | 121 | { |
| 122 | /* count chars to quote */ | ||
| 123 | int len = 0, n = 0; | 122 | int len = 0, n = 0; |
| 124 | int force_quotes = 0; | 123 | int force_quotes = 0; |
| 125 | char *q, *d; | 124 | char *q, *d; |
| 126 | const char *p = arg; | 125 | const char *p = arg; |
| 127 | if (!*p) force_quotes = 1; | 126 | |
| 127 | /* empty arguments must be quoted */ | ||
| 128 | if (!*p) { | ||
| 129 | force_quotes = 1; | ||
| 130 | } | ||
| 131 | |||
| 128 | while (*p) { | 132 | while (*p) { |
| 129 | if (isspace(*p)) | 133 | if (isspace(*p)) { |
| 134 | /* arguments containing whitespace must be quoted */ | ||
| 130 | force_quotes = 1; | 135 | force_quotes = 1; |
| 131 | else if (*p == '"') | 136 | } |
| 137 | else if (*p == '"') { | ||
| 138 | /* double quotes in arguments need to be escaped */ | ||
| 132 | n++; | 139 | n++; |
| 140 | } | ||
| 133 | else if (*p == '\\') { | 141 | else if (*p == '\\') { |
| 142 | /* count contiguous backslashes */ | ||
| 134 | int count = 0; | 143 | int count = 0; |
| 135 | while (*p == '\\') { | 144 | while (*p == '\\') { |
| 136 | count++; | 145 | count++; |
| 137 | p++; | 146 | p++; |
| 138 | len++; | 147 | len++; |
| 139 | } | 148 | } |
| 140 | if (*p == '"') | 149 | |
| 150 | /* | ||
| 151 | * Only escape backslashes before explicit double quotes or | ||
| 152 | * or where the backslashes are at the end of an argument | ||
| 153 | * that is scheduled to be quoted. | ||
| 154 | */ | ||
| 155 | if (*p == '"' || (force_quotes && *p == '\0')) { | ||
| 141 | n += count*2 + 1; | 156 | n += count*2 + 1; |
| 157 | } | ||
| 158 | |||
| 159 | if (*p == '\0') { | ||
| 160 | break; | ||
| 161 | } | ||
| 142 | continue; | 162 | continue; |
| 143 | } | 163 | } |
| 144 | len++; | 164 | len++; |
| 145 | p++; | 165 | p++; |
| 146 | } | 166 | } |
| 147 | if (!force_quotes && n == 0) | 167 | |
| 168 | if (!force_quotes && n == 0) { | ||
| 148 | return (char*)arg; | 169 | return (char*)arg; |
| 170 | } | ||
| 149 | 171 | ||
| 150 | /* insert \ where necessary */ | 172 | /* insert double quotes and backslashes where necessary */ |
| 151 | d = q = xmalloc(len+n+3); | 173 | d = q = xmalloc(len+n+3); |
| 152 | if (force_quotes) | 174 | if (force_quotes) { |
| 153 | *d++ = '"'; | 175 | *d++ = '"'; |
| 176 | } | ||
| 177 | |||
| 154 | while (*arg) { | 178 | while (*arg) { |
| 155 | if (*arg == '"') | 179 | if (*arg == '"') { |
| 156 | *d++ = '\\'; | 180 | *d++ = '\\'; |
| 181 | } | ||
| 157 | else if (*arg == '\\') { | 182 | else if (*arg == '\\') { |
| 158 | int count = 0; | 183 | int count = 0; |
| 159 | while (*arg == '\\') { | 184 | while (*arg == '\\') { |
| 160 | count++; | 185 | count++; |
| 161 | *d++ = *arg++; | 186 | *d++ = *arg++; |
| 162 | } | 187 | } |
| 163 | if (*arg == '"') { | 188 | |
| 164 | while (count-- > 0) | 189 | if (*arg == '"' || (force_quotes && *arg == '\0')) { |
| 190 | while (count-- > 0) { | ||
| 165 | *d++ = '\\'; | 191 | *d++ = '\\'; |
| 166 | *d++ = '\\'; | 192 | } |
| 193 | if (*arg == '"') { | ||
| 194 | *d++ = '\\'; | ||
| 195 | } | ||
| 167 | } | 196 | } |
| 168 | } | 197 | } |
| 169 | *d++ = *arg++; | 198 | if (*arg != '\0') { |
| 199 | *d++ = *arg++; | ||
| 200 | } | ||
| 170 | } | 201 | } |
| 171 | if (force_quotes) | 202 | if (force_quotes) { |
| 172 | *d++ = '"'; | 203 | *d++ = '"'; |
| 173 | *d++ = 0; | 204 | } |
| 205 | *d = '\0'; | ||
| 206 | |||
| 174 | return q; | 207 | return q; |
| 175 | } | 208 | } |
| 176 | 209 | ||
