Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2011-08-05 11:15:04 +0400
committerBert Belder <bertbelder@gmail.com>2011-08-05 11:15:04 +0400
commit08782931205bc4f6d28102ebc29fd806e8ccdf1f (patch)
tree994eda1c3ca8dad92d942b3444dae999ba22a8b9 /deps
parent30d20cf40595e5d0c31b6d3cab9afc9fe8c54bfb (diff)
Upgrade libuv to c834d5de9e4747e5138bed9140320b44622ab6de
Diffstat (limited to 'deps')
-rw-r--r--deps/uv/include/uv.h1
-rw-r--r--deps/uv/src/win/process.c140
-rw-r--r--deps/uv/test/test-list.h2
-rw-r--r--deps/uv/test/test-spawn.c73
4 files changed, 163 insertions, 53 deletions
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index bb3e37c45d6..2ee7c315f2b 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -504,6 +504,7 @@ typedef struct uv_process_options_s {
char** args;
char** env;
char* cwd;
+ int windows_verbatim_arguments;
/*
* The user should supply pointers to initialized uv_pipe_t structs for
* stdio. The user is reponsible for calling uv_close on them.
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 489c2a16c86..7b4b562e85a 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -76,48 +76,6 @@ static void uv_process_init(uv_process_t* handle) {
/*
- * Quotes command line arguments
- * Returns a pointer to the end (next char to be written) of the buffer
- */
-static wchar_t* quote_cmd_arg(wchar_t *source, wchar_t *target,
- wchar_t terminator) {
- int len = wcslen(source),
- i;
-
- // Check if the string must be quoted;
- // if unnecessary, don't do it, it may only confuse older programs.
- if (len == 0) {
- goto quote;
- }
- for (i = 0; i < len; i++) {
- if (source[i] == L' ' || source[i] == L'"') {
- goto quote;
- }
- }
-
- // No quotation needed
- wcsncpy(target, source, len);
- target += len;
- *(target++) = terminator;
- return target;
-
-quote:
- // Quote
- *(target++) = L'"';
- for (i = 0; i < len; i++) {
- if (source[i] == L'"' || source[i] == L'\\') {
- *(target++) = '\\';
- }
- *(target++) = source[i];
- }
- *(target++) = L'"';
- *(target++) = terminator;
-
- return target;
-}
-
-
-/*
* Path search functions
*/
@@ -403,8 +361,83 @@ static wchar_t* search_path(const wchar_t *file,
return result;
}
+/*
+ * Quotes command line arguments
+ * Returns a pointer to the end (next char to be written) of the buffer
+ */
+wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
+ int len = wcslen(source),
+ i, quote_hit;
+ wchar_t* start;
+
+ /*
+ * Check if the string must be quoted;
+ * if unnecessary, don't do it, it may only confuse older programs.
+ */
+ if (len == 0) {
+ return target;
+ }
+
+ if (NULL == wcspbrk(source, L" \t\"")) {
+ /* No quotation needed */
+ wcsncpy(target, source, len);
+ target += len;
+ return target;
+ }
+
+ if (NULL == wcspbrk(source, L"\"\\")) {
+ /*
+ * No embedded double quotes or backlashes, so I can just wrap
+ * quote marks around the whole thing.
+ */
+ *(target++) = L'"';
+ wcsncpy(target, source, len);
+ target += len;
+ *(target++) = L'"';
+ return target;
+ }
+
+ /*
+ * Expected intput/output:
+ * input : hello"world
+ * output: "hello\"world"
+ * input : hello""world
+ * output: "hello\"\"world"
+ * input : hello\world
+ * output: hello\world
+ * input : hello\\world
+ * output: hello\\world
+ * input : hello\"world
+ * output: "hello\\\"world"
+ * input : hello\\"world
+ * output: "hello\\\\\"world"
+ * input : hello world\
+ * output: "hello world\"
+ */
+
+ *(target++) = L'"';
+ start = target;
+ quote_hit = 1;
+
+ for (i = len; i > 0; --i) {
+ *(target++) = source[i - 1];
-static wchar_t* make_program_args(char** args) {
+ if (quote_hit && source[i - 1] == L'\\') {
+ *(target++) = L'\\';
+ } else if(source[i - 1] == L'"') {
+ quote_hit = 1;
+ *(target++) = L'\\';
+ } else {
+ quote_hit = 0;
+ }
+ }
+ target[0] = L'\0';
+ wcsrev(start);
+ *(target++) = L'"';
+ return target;
+}
+
+wchar_t* make_program_args(char** args, int verbatim_arguments) {
wchar_t* dst;
wchar_t* ptr;
char** arg;
@@ -423,13 +456,9 @@ static wchar_t* make_program_args(char** args) {
arg_count++;
}
- /* Adjust for potential quotes. */
- size *= 2;
-
- /* Arguments are separated with a space. */
- if (arg_count > 0) {
- size += arg_count - 1;
- }
+ /* Adjust for potential quotes. Also assume the worst-case scenario
+ /* that every character needs escaping, so we need twice as much space. */
+ size = size * 2 + arg_count * 2;
dst = (wchar_t*)malloc(size);
if (!dst) {
@@ -447,8 +476,13 @@ static wchar_t* make_program_args(char** args) {
if (!len) {
goto error;
}
-
- ptr = quote_cmd_arg(buffer, ptr, *(arg + 1) ? L' ' : L'\0');
+ if (verbatim_arguments) {
+ wcscpy(ptr, buffer);
+ ptr += len - 1;
+ } else {
+ ptr = quote_cmd_arg(buffer, ptr);
+ }
+ *ptr++ = *(arg + 1) ? L' ' : L'\0';
}
free(buffer);
@@ -743,7 +777,7 @@ int uv_spawn(uv_process_t* process, uv_process_options_t options) {
process->exit_cb = options.exit_cb;
UTF8_TO_UTF16(options.file, application);
- arguments = options.args ? make_program_args(options.args) : NULL;
+ arguments = options.args ? make_program_args(options.args, options.windows_verbatim_arguments) : NULL;
env = options.env ? make_program_env(options.env) : NULL;
if (options.cwd) {
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index ebfdeb65569..08ed92a2bdd 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -69,6 +69,7 @@ TEST_DECLARE (spawn_stdin)
TEST_DECLARE (spawn_and_kill)
#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
+TEST_DECLARE (argument_escaping)
#endif
HELPER_DECLARE (tcp4_echo_server)
HELPER_DECLARE (tcp6_echo_server)
@@ -153,6 +154,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_and_kill)
#ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
+ TEST_ENTRY (argument_escaping)
#endif
#if 0
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 6378aab9811..18a9bb7d978 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -269,4 +269,77 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
return 0;
}
+
+
+wchar_t* make_program_args(char** args, int verbatim_arguments);
+wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target);
+
+TEST_IMPL(argument_escaping) {
+ const wchar_t* test_str[] = {
+ L"HelloWorld",
+ L"Hello World",
+ L"Hello\"World",
+ L"Hello World\\",
+ L"Hello\\\"World",
+ L"Hello\\World",
+ L"Hello\\\\World",
+ L"Hello World\\",
+ L"c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\""
+ };
+ const int count = sizeof(test_str) / sizeof(*test_str);
+ wchar_t** test_output;
+ wchar_t* command_line;
+ wchar_t** cracked;
+ size_t total_size = 0;
+ int i;
+ int num_args;
+
+ char* verbatim[] = {
+ "cmd.exe",
+ "/c",
+ "c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"",
+ NULL
+ };
+ wchar_t* verbatim_output;
+ wchar_t* non_verbatim_output;
+
+ test_output = calloc(count, sizeof(wchar_t*));
+ for (i = 0; i < count; ++i) {
+ test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(wchar_t));
+ quote_cmd_arg(test_str[i], test_output[i]);
+ wprintf(L"input : %s\n", test_str[i]);
+ wprintf(L"output: %s\n", test_output[i]);
+ total_size += wcslen(test_output[i]) + 1;
+ }
+ command_line = calloc(total_size + 1, sizeof(wchar_t));
+ for (i = 0; i < count; ++i) {
+ wcscat(command_line, test_output[i]);
+ wcscat(command_line, L" ");
+ }
+ command_line[total_size - 1] = L'\0';
+
+ wprintf(L"command_line: %s\n", command_line);
+
+ cracked = CommandLineToArgvW(command_line, &num_args);
+ for (i = 0; i < num_args; ++i) {
+ wprintf(L"%d: %s\t%s\n", i, test_str[i], cracked[i]);
+ ASSERT(wcscmp(test_str[i], cracked[i]) == 0);
+ }
+
+ LocalFree(cracked);
+ for (i = 0; i < count; ++i) {
+ free(test_output[i]);
+ }
+
+ verbatim_output = make_program_args(verbatim, 1);
+ non_verbatim_output = make_program_args(verbatim, 0);
+
+ wprintf(L" verbatim_output: %s\n", verbatim_output);
+ wprintf(L"non_verbatim_output: %s\n", non_verbatim_output);
+
+ ASSERT(wcscmp(verbatim_output, L"cmd.exe /c c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"") == 0);
+ ASSERT(wcscmp(non_verbatim_output, L"cmd.exe /c \"c:\\path\\to\\node.exe --eval \\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0);
+
+ return 0;
+}
#endif \ No newline at end of file