diff options
author | Uoti Urpala <uau@mplayer2.org> | 2011-08-05 03:21:14 +0300 |
---|---|---|
committer | Uoti Urpala <uau@mplayer2.org> | 2011-08-05 03:21:14 +0300 |
commit | fddb59a6c3b06ecca9b4e755af4a5e6bccd20615 (patch) | |
tree | c38deafbe891b943fd2bca3ab7c71d329ee12dcb /input | |
parent | 35ef4d02d01a537357b35c3c3e5d729846777c5e (diff) | |
download | mpv-fddb59a6c3b06ecca9b4e755af4a5e6bccd20615.tar.bz2 mpv-fddb59a6c3b06ecca9b4e755af4a5e6bccd20615.tar.xz |
commands: parsing: fix string argument quoting/escaping
Parsing of commands with string arguments had several problems. First,
escape handling modified the original string, which broke keyboard
command definitions with strings containing escapes. Second, in an
argument like "\\" the second quote was incorrectly considered escaped
even though the preceding '\' was itself escaped. Third, an
unterminated quoted string resulted in the argument being set to NULL
even if this violated the declared the minimum number of arguments to
the command type; this could cause a crash in the code executing the
parsed commands. Fix by rewriting the string argument parsing. Also
change int/float argument parsing so that the whole command is
rejected on error.
Diffstat (limited to 'input')
-rw-r--r-- | input/input.c | 64 |
1 files changed, 26 insertions, 38 deletions
diff --git a/input/input.c b/input/input.c index f77dddfa91..e1feb8e8e4 100644 --- a/input/input.c +++ b/input/input.c @@ -860,7 +860,7 @@ mp_cmd_t *mp_input_parse_cmd(char *str) { int i, l; int pausing = 0; - char *ptr, *e; + char *ptr; const mp_cmd_t *cmd_def; // Ignore heading spaces. @@ -926,7 +926,7 @@ mp_cmd_t *mp_input_parse_cmd(char *str) if (errno != 0) { mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d " "isn't an integer.\n", cmd_def->name, i + 1); - ptr = NULL; + goto error; } break; case MP_CMD_ARG_FLOAT: @@ -935,45 +935,31 @@ mp_cmd_t *mp_input_parse_cmd(char *str) if (errno != 0) { mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d " "isn't a float.\n", cmd_def->name, i + 1); - ptr = NULL; + goto error; } break; case MP_CMD_ARG_STRING: { - char term; - char *ptr2 = ptr, *start; - - if (ptr[0] == '\'' || ptr[0] == '"') { - term = ptr[0]; - ptr2++; - } else - term = ' '; - start = ptr2; + int term = ' '; + if (*ptr == '\'' || *ptr == '"') + term = *ptr++; + char *argptr = talloc_size(cmd, strlen(ptr) + 1); + cmd->args[i].v.s = argptr; while (1) { - e = strchr(ptr2, term); - if (!e) - break; - if (e <= ptr2 || *(e - 1) != '\\') + if (*ptr == 0) { + if (term == ' ') + break; + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is " + "unterminated.\n", cmd_def->name, i + 1); + goto error; + } + if (*ptr == term) break; - ptr2 = e + 1; + if (*ptr == '\\') + ptr++; + if (*ptr != 0) + *argptr++ = *ptr++; } - - if (term != ' ' && (!e || e[0] == '\0')) { - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is " - "unterminated.\n", cmd_def->name, i + 1); - ptr = NULL; - break; - } else if (!e) - e = ptr + strlen(ptr); - l = e - start; - ptr2 = start; - for (e = strchr(ptr2, '\\'); e && e < start + l; e = strchr(ptr2, '\\')) { - memmove(e, e + 1, strlen(e)); - ptr2 = e + 1; - l--; - } - cmd->args[i].v.s = talloc_strndup(cmd, start, l); - if (term != ' ') - ptr += l + 2; + *argptr = 0; break; } case -1: @@ -986,12 +972,10 @@ mp_cmd_t *mp_input_parse_cmd(char *str) cmd->nargs = i; if (cmd_def->nargs > cmd->nargs) { -/* mp_msg(MSGT_INPUT, MSGL_ERR, "Got command '%s' but\n", str); */ mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s requires at least %d " "arguments, we found only %d so far.\n", cmd_def->name, cmd_def->nargs, cmd->nargs); - mp_cmd_free(cmd); - return NULL; + goto error; } for (; i < MP_CMD_MAX_ARGS && cmd_def->args[i].type != -1; i++) { @@ -1005,6 +989,10 @@ mp_cmd_t *mp_input_parse_cmd(char *str) cmd->args[i].type = -1; return cmd; + + error: + mp_cmd_free(cmd); + return NULL; } #define MP_CMD_MAX_SIZE 4096 |