summaryrefslogtreecommitdiffstats
path: root/input/input.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-08-05 03:21:14 +0300
committerUoti Urpala <uau@mplayer2.org>2011-08-05 03:21:14 +0300
commitfddb59a6c3b06ecca9b4e755af4a5e6bccd20615 (patch)
treec38deafbe891b943fd2bca3ab7c71d329ee12dcb /input/input.c
parent35ef4d02d01a537357b35c3c3e5d729846777c5e (diff)
downloadmpv-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/input.c')
-rw-r--r--input/input.c64
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