Commit 104fc302 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

qmp: Drop duplicated QMP command object checks



qmp_check_input_obj() duplicates qmp_dispatch_check_obj(), except the
latter screws up an error message.  handle_qmp_command() runs first
the former, then the latter via qmp_dispatch(), masking the screwup.

qemu-ga also masks the screwup, because it also duplicates checks,
just differently.

qmp_check_input_obj() exists because handle_qmp_command() needs to
examine the command before dispatching it.  The previous commit got
rid of this need, except for a tracepoint, and a bit of "id" code that
relies on qdict not being null.

Fix up the error message in qmp_dispatch_check_obj(), drop
qmp_check_input_obj() and the tracepoint.  Protect the "id" code with
a conditional.

Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Message-Id: <1488544368-30622-9-git-send-email-armbru@redhat.com>
parent 635db18f
Loading
Loading
Loading
Loading
+6 −68
Original line number Diff line number Diff line
@@ -3700,67 +3700,10 @@ static int monitor_can_read(void *opaque)
    return (mon->suspend_cnt == 0) ? 1 : 0;
}

/*
 * 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, Error **errp)
{
    const QDictEntry *ent;
    int has_exec_key = 0;
    QDict *input_dict;

    input_dict = qobject_to_qdict(input_obj);
    if (!input_dict) {
        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
        return NULL;
    }


    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) {
                error_setg(errp, 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) {
                error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
                           "arguments", "object");
                return NULL;
            }
        } else if (!strcmp(arg_name, "id")) {
            /* Any string is acceptable as "id", so nothing to check */
        } else {
            error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
            return NULL;
        }
    }

    if (!has_exec_key) {
        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
        return NULL;
    }

    return input_dict;
}

static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
{
    QObject *req, *rsp = NULL, *id = NULL;
    QDict *qdict = NULL;
    const char *cmd_name;
    Monitor *mon = cur_mon;
    Error *err = NULL;

@@ -3773,17 +3716,12 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
        goto err_out;
    }

    qdict = qmp_check_input_obj(req, &err);
    if (!qdict) {
        goto err_out;
    }

    qdict = qobject_to_qdict(req);
    if (qdict) {
        id = qdict_get(qdict, "id");
        qobject_incref(id);
        qdict_del(qdict, "id");

    cmd_name = qdict_get_str(qdict, "execute");
    trace_handle_qmp_command(mon, cmd_name);
    } /* else will fail qmp_dispatch() */

    rsp = qmp_dispatch(cur_mon->qmp.commands, req);

+1 −2
Original line number Diff line number Diff line
@@ -30,8 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)

    dict = qobject_to_qdict(request);
    if (!dict) {
        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT,
                   "request is not a dictionary");
        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
        return NULL;
    }

+0 −1
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ xen_remap_bucket(uint64_t index) "index %#"PRIx64
xen_map_cache_return(void* ptr) "%p"

# monitor.c
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p"
monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p"
monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event=%d data=%p rate=%" PRId64