Currently a command that takes two consecutive integer operations, like client_migrate_info, will be incorrectly parsed by the human monitor if the second expression begins with a minus ('-') or plus ('+') sign:
client_migrate_info <protocol> <hostname> <port> <tls-port> client_migrate_info spice localhost 5900 -1 => port = 5899 = 5900 - 1 tls-port = -1 But expected by the user to be: port = 5900 tls-port = -1 The fix is that for any required integer (ilM) expression followed by another integer expression (ilM) the first expression will be parsed by expr_unary instead of expr_sum. So you can still use arithmetic, but you have to enclose it in parenthesis: Command line | Old parsed result | With patch result (1+1) 2 | 2, 2 | 2, 2 1 -1 | 0, -1 | 1, -1 The rest are bizarre but not any worse then before 1+2+3 | 6, 5 | 1, 5 (1+2)+3 | 3, 3 | 3, 3 Signed-off-by: Alon Levy <al...@redhat.com> --- monitor.c | 27 ++++++++++++++++++++++++--- 1 files changed, 24 insertions(+), 3 deletions(-) diff --git a/monitor.c b/monitor.c index 1b8ba2c..45e2d6c 100644 --- a/monitor.c +++ b/monitor.c @@ -3889,7 +3889,7 @@ static int64_t expr_sum(Monitor *mon) return val; } -static int get_expr(Monitor *mon, int64_t *pval, const char **pp) +static int get_expr(Monitor *mon, int64_t *pval, const char **pp, int unary) { pch = *pp; if (setjmp(expr_env)) { @@ -3898,7 +3898,11 @@ static int get_expr(Monitor *mon, int64_t *pval, const char **pp) } while (qemu_isspace(*pch)) pch++; - *pval = expr_sum(mon); + if (unary) { + *pval = expr_unary(mon); + } else { + *pval = expr_sum(mon); + } *pp = pch; return 0; } @@ -4267,6 +4271,9 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, case 'M': { int64_t val; + int unary = 0; + char *next_key; + char *next; while (qemu_isspace(*p)) p++; @@ -4288,7 +4295,21 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, } typestr++; } - if (get_expr(mon, &val, &p)) + next = key_get_info(typestr, &next_key); + qemu_free(next_key); + if (*next == 'i' || *next == 'l' || *next == 'M') { + /* If a command has two consecutive ii parameters the first + * get_expr will also parse the second parameter if it + * starts with a - or +. To avoid this only parse unary in + * this case, i.e.: + * client_migrate_info spice localhost 1 -1 + * => 1, -1 + * client_migrate_info spice localhost (1+3) -1 + * => 4, -1 + */ + unary = 1; + } + if (get_expr(mon, &val, &p, unary)) goto fail; /* Check if 'i' is greater than 32-bit */ if ((c == 'i') && ((val >> 32) & 0xffffffff)) { -- 1.7.6