win/pty: quote_cmd_arg(): check bounds

This commit is contained in:
erw7 2017-03-30 18:30:40 +09:00 committed by Justin M. Keyes
parent e635754e8e
commit 3b992f1688

View File

@ -210,9 +210,10 @@ static int build_cmdline(char **argv, wchar_t **cmdline)
QUEUE_INIT(&q); QUEUE_INIT(&q);
while (*argv) { while (*argv) {
size_t buf_len = strlen(*argv) * 2 + 3;
arg_T *arg = xmalloc(sizeof(arg_T)); arg_T *arg = xmalloc(sizeof(arg_T));
arg->arg = (char *)xmalloc(strlen(*argv) * 2 + 3); arg->arg = (char *)xmalloc(buf_len);
quote_cmd_arg(arg->arg, *argv); quote_cmd_arg(arg->arg, buf_len, *argv);
args_len += strlen(arg->arg); args_len += strlen(arg->arg);
QUEUE_INIT(&arg->node); QUEUE_INIT(&arg->node);
QUEUE_INSERT_TAIL(&q, &arg->node); QUEUE_INSERT_TAIL(&q, &arg->node);
@ -241,50 +242,50 @@ static int build_cmdline(char **argv, wchar_t **cmdline)
} }
// Emulate quote_cmd_arg of libuv and quotes command line arguments // Emulate quote_cmd_arg of libuv and quotes command line arguments
static void quote_cmd_arg(char *target, const char *source) static void quote_cmd_arg(char *target, size_t remain, const char *source)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
size_t len = strlen(source); size_t src_len = strlen(source);
size_t i; size_t i;
bool quote_hit = true; bool quote_hit = true;
char *start = target; char *start = target;
char tmp; char tmp;
if (len == 0) { if (src_len == 0) {
*(target++) = '"'; snprintf(target, remain, "\"\"");
*(target++) = '"';
*target = NUL;
return; return;
} }
if (NULL == strpbrk(source, " \t\"")) { if (NULL == strpbrk(source, " \t\"")) {
strcpy(target, source); xstrlcpy(target, source, remain);
return; return;
} }
if (NULL == strpbrk(source, "\"\\")) { if (NULL == strpbrk(source, "\"\\")) {
*(target++) = '"'; snprintf(target, remain, "\"%s\"", source);
strncpy(target, source, len);
target += len;
*(target++) = '"';
*target = NUL;
return; return;
} }
assert(remain--);
*(target++) = NUL; *(target++) = NUL;
assert(remain--);
*(target++) = '"'; *(target++) = '"';
for (i = len; i > 0; --i) { for (i = src_len; i > 0; i--) {
assert(remain--);
*(target++) = source[i - 1]; *(target++) = source[i - 1];
if (quote_hit && source[i - 1] == '\\') { if (quote_hit && source[i - 1] == '\\') {
assert(remain--);
*(target++) = '\\'; *(target++) = '\\';
} else if (source[i - 1] == '"') { } else if (source[i - 1] == '"') {
quote_hit = true; quote_hit = true;
assert(remain--);
*(target++) = '\\'; *(target++) = '\\';
} else { } else {
quote_hit = false; quote_hit = false;
} }
} }
assert(remain);
*target = '"'; *target = '"';
while (start < target) { while (start < target) {
tmp = *start; tmp = *start;