Browse Source

Upgrade libuv to c834d5de9e4747e5138bed9140320b44622ab6de

v0.7.4-release
Bert Belder 14 years ago
parent
commit
0878293120
  1. 1
      deps/uv/include/uv.h
  2. 140
      deps/uv/src/win/process.c
  3. 2
      deps/uv/test/test-list.h
  4. 73
      deps/uv/test/test-spawn.c

1
deps/uv/include/uv.h

@ -504,6 +504,7 @@ typedef struct uv_process_options_s {
char** args; char** args;
char** env; char** env;
char* cwd; char* cwd;
int windows_verbatim_arguments;
/* /*
* The user should supply pointers to initialized uv_pipe_t structs for * The user should supply pointers to initialized uv_pipe_t structs for
* stdio. The user is reponsible for calling uv_close on them. * stdio. The user is reponsible for calling uv_close on them.

140
deps/uv/src/win/process.c

@ -75,48 +75,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 * Path search functions
*/ */
@ -403,8 +361,83 @@ static wchar_t* search_path(const wchar_t *file,
return result; 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* dst;
wchar_t* ptr; wchar_t* ptr;
char** arg; char** arg;
@ -423,13 +456,9 @@ static wchar_t* make_program_args(char** args) {
arg_count++; arg_count++;
} }
/* Adjust for potential quotes. */ /* Adjust for potential quotes. Also assume the worst-case scenario
size *= 2; /* that every character needs escaping, so we need twice as much space. */
size = size * 2 + arg_count * 2;
/* Arguments are separated with a space. */
if (arg_count > 0) {
size += arg_count - 1;
}
dst = (wchar_t*)malloc(size); dst = (wchar_t*)malloc(size);
if (!dst) { if (!dst) {
@ -447,8 +476,13 @@ static wchar_t* make_program_args(char** args) {
if (!len) { if (!len) {
goto error; goto error;
} }
if (verbatim_arguments) {
ptr = quote_cmd_arg(buffer, ptr, *(arg + 1) ? L' ' : L'\0'); wcscpy(ptr, buffer);
ptr += len - 1;
} else {
ptr = quote_cmd_arg(buffer, ptr);
}
*ptr++ = *(arg + 1) ? L' ' : L'\0';
} }
free(buffer); free(buffer);
@ -743,7 +777,7 @@ int uv_spawn(uv_process_t* process, uv_process_options_t options) {
process->exit_cb = options.exit_cb; process->exit_cb = options.exit_cb;
UTF8_TO_UTF16(options.file, application); 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; env = options.env ? make_program_env(options.env) : NULL;
if (options.cwd) { if (options.cwd) {

2
deps/uv/test/test-list.h

@ -69,6 +69,7 @@ TEST_DECLARE (spawn_stdin)
TEST_DECLARE (spawn_and_kill) TEST_DECLARE (spawn_and_kill)
#ifdef _WIN32 #ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
TEST_DECLARE (argument_escaping)
#endif #endif
HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp4_echo_server)
HELPER_DECLARE (tcp6_echo_server) HELPER_DECLARE (tcp6_echo_server)
@ -153,6 +154,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_and_kill) TEST_ENTRY (spawn_and_kill)
#ifdef _WIN32 #ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
TEST_ENTRY (argument_escaping)
#endif #endif
#if 0 #if 0

73
deps/uv/test/test-spawn.c

@ -269,4 +269,77 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
return 0; 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 #endif
Loading…
Cancel
Save