diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-01-23 18:37:26 -0800 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-01-23 18:37:26 -0800 |
| commit | 7da3733c73e7a3ba4c18f3927bbbe185598ad233 (patch) | |
| tree | 614a49b6f74c81a42faf9fbdec3b59f8886e0af4 /src/rt/rust_run_program.cpp | |
| parent | 7c1d1d6c9a63e76e24ac31bad96940ab1fb44d0f (diff) | |
| download | rust-7da3733c73e7a3ba4c18f3927bbbe185598ad233.tar.gz rust-7da3733c73e7a3ba4c18f3927bbbe185598ad233.zip | |
Fix win32 command-line quoting on rust_run_program.
Diffstat (limited to 'src/rt/rust_run_program.cpp')
| -rw-r--r-- | src/rt/rust_run_program.cpp | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/src/rt/rust_run_program.cpp b/src/rt/rust_run_program.cpp index 1b17a510b2e..df4714758dd 100644 --- a/src/rt/rust_run_program.cpp +++ b/src/rt/rust_run_program.cpp @@ -5,6 +5,64 @@ #include <process.h> #include <io.h> +bool backslash_run_ends_in_quote(char const *c) { + while (*c == '\\') ++c; + return *c == '"'; +} + +void append_first_char(char *&buf, char const *c) { + switch (*c) { + + case '"': + // Escape quotes. + *buf++ = '\\'; + *buf++ = '"'; + break; + + + case '\\': + if (backslash_run_ends_in_quote(c)) { + // Double all backslashes that are in runs before quotes. + *buf++ = '\\'; + *buf++ = '\\'; + } else { + // Pass other backslashes through unescaped. + *buf++ = '\\'; + } + break; + + default: + *buf++ = *c; + } +} + +bool contains_whitespace(char const *arg) { + while (*arg) { + switch (*arg++) { + case ' ': + case '\t': + return true; + } + } + return false; +} + +void append_arg(char *& buf, char const *arg, bool last) { + bool quote = contains_whitespace(arg); + if (quote) + *buf++ = '"'; + while (*arg) + append_first_char(buf, arg++); + if (quote) + *buf++ = '"'; + + if (! last) { + *buf++ = ' '; + } else { + *buf++ = '\0'; + } +} + extern "C" CDECL int rust_run_program(const char* argv[], int in_fd, int out_fd, int err_fd) { STARTUPINFO si; @@ -29,14 +87,14 @@ rust_run_program(const char* argv[], int in_fd, int out_fd, int err_fd) { size_t cmd_len = 0; for (const char** arg = argv; *arg; arg++) { cmd_len += strlen(*arg); - cmd_len++; // Space or \0 + cmd_len += 3; // Two quotes plus trailing space or \0 } + cmd_len *= 2; // Potentially backslash-escape everything. + char* cmd = (char*)malloc(cmd_len); char* pos = cmd; for (const char** arg = argv; *arg; arg++) { - strcpy(pos, *arg); - pos += strlen(*arg); - if (*(arg+1)) *(pos++) = ' '; + append_arg(pos, *arg, *(arg+1) == NULL); } PROCESS_INFORMATION pi; |
