diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 62 |
1 files changed, 61 insertions, 1 deletions
@@ -4169,6 +4169,62 @@ out: return err; } +/* + * Input object checking rules + * + * 1. Input object must be a dict + * 2. The "execute" key must exist + * 3. The "execute" key must be a string + * 4. If the "arguments" key exists, it must be a dict + * 5. If the "id" key exists, it can be anything (ie. json-value) + * 6. Any argument not listed above is considered invalid + */ +static QDict *qmp_check_input_obj(QObject *input_obj) +{ + const QDictEntry *ent; + int has_exec_key = 0; + QDict *input_dict; + + if (qobject_type(input_obj) != QTYPE_QDICT) { + qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object"); + return NULL; + } + + input_dict = qobject_to_qdict(input_obj); + + for (ent = qdict_first(input_dict); ent; ent = qdict_next(input_dict, ent)){ + const char *arg_name = qdict_entry_key(ent); + const QObject *arg_obj = qdict_entry_value(ent); + + if (!strcmp(arg_name, "execute")) { + if (qobject_type(arg_obj) != QTYPE_QSTRING) { + qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", + "string"); + return NULL; + } + has_exec_key = 1; + } else if (!strcmp(arg_name, "arguments")) { + if (qobject_type(arg_obj) != QTYPE_QDICT) { + qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", + "object"); + return NULL; + } + } else if (!strcmp(arg_name, "id")) { + /* FIXME: check duplicated IDs for async commands */ + } else { + qerror_report(QERR_QMP_EXTRA_MEMBER, arg_name); + return NULL; + } + } + + if (!has_exec_key) { + qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute"); + return NULL; + } + + return input_dict; +} + static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { int err; @@ -4191,7 +4247,11 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - input = qobject_to_qdict(obj); + input = qmp_check_input_obj(obj); + if (!input) { + qobject_decref(obj); + goto err_out; + } mon->mc->id = qdict_get(input, "id"); qobject_incref(mon->mc->id); |