From patchwork Tue Jun 22 17:40:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 56554 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0861FB6F01 for ; Wed, 23 Jun 2010 03:57:00 +1000 (EST) Received: from localhost ([127.0.0.1]:44564 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OR7iT-0005g1-7K for incoming@patchwork.ozlabs.org; Tue, 22 Jun 2010 13:56:57 -0400 Received: from [140.186.70.92] (port=55600 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OR7TZ-0004aA-G4 for qemu-devel@nongnu.org; Tue, 22 Jun 2010 13:41:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OR7TM-0000dS-Bl for qemu-devel@nongnu.org; Tue, 22 Jun 2010 13:41:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40563) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OR7TM-0000dG-5A for qemu-devel@nongnu.org; Tue, 22 Jun 2010 13:41:20 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5MHfJBq024924 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 22 Jun 2010 13:41:19 -0400 Received: from localhost (vpn-10-15.rdu.redhat.com [10.11.10.15]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5MHfIm5029196; Tue, 22 Jun 2010 13:41:18 -0400 From: Luiz Capitulino To: qemu-devel@nongnu.org Date: Tue, 22 Jun 2010 14:40:46 -0300 Message-Id: <1277228451-7741-9-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1277228451-7741-1-git-send-email-lcapitulino@redhat.com> References: <1277228451-7741-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: armbru@redhat.com Subject: [Qemu-devel] [PATCH 08/13] QMP: New argument checker (first part) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Current QMP's argument checker is more complex than it should be and has (at least) one serious bug: it ignores unknown arguments. To solve both problems we introduce a new argument checker. It's added on top of the existing one, so that there are no regressions during the transition. This commit introduces the first part of the new checker, which is run by qmp_check_client_args() and does the following: 1. Check if all mandatory arguments were provided 2. Set flags for argument validation In order to do that, we transform the args_type string (from qemu-montor.hx) into a qdict and iterate over it. Next commit adds the new checker's second part: type checking and invalid argument detection. Signed-off-by: Luiz Capitulino --- monitor.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 106 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index 3df8174..b4fe5ba 100644 --- a/monitor.c +++ b/monitor.c @@ -177,6 +177,9 @@ static inline void mon_print_count_init(Monitor *mon) { } static inline int mon_print_count_get(const Monitor *mon) { return 0; } #endif /* CONFIG_DEBUG_MONITOR */ +/* QMP checker flags */ +#define QMP_CHECKER_OTYPE 1 /* O-type argument is present */ + static QLIST_HEAD(mon_list, Monitor) mon_list; static const mon_cmd_t mon_cmds[]; @@ -4135,6 +4138,104 @@ static int invalid_qmp_mode(const Monitor *mon, const char *cmd_name) return (qmp_cmd_mode(mon) ? is_cap : !is_cap); } +/* + * - Check if the client has passed all mandatory args + * - Set special flags for argument validation + */ +static int check_mandatory_args(const QDict *cmd_args, + const QDict *client_args, int *flags) +{ + const QDictEntry *ent; + + for (ent = qdict_first(cmd_args); ent; ent = qdict_next(cmd_args, ent)) { + const char *cmd_arg_name = qdict_entry_key(ent); + QString *type = qobject_to_qstring(qdict_entry_value(ent)); + assert(type != NULL); + + if (qstring_get_str(type)[0] == 'O') { + assert((*flags & QMP_CHECKER_OTYPE) == 0); + *flags |= QMP_CHECKER_OTYPE; + } else if (qstring_get_str(type)[0] != '-' && + qstring_get_str(type)[1] != '?' && + !qdict_haskey(client_args, cmd_arg_name)) { + qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name); + return -1; + } + } + + return 0; +} + +static QDict *qdict_from_args_type(const char *args_type) +{ + int i; + QDict *qdict; + QString *key, *type, *cur_qs; + + assert(args_type != NULL); + + qdict = qdict_new(); + + if (args_type == NULL || args_type[0] == '\0') { + /* no args, empty qdict */ + goto out; + } + + key = qstring_new(); + type = qstring_new(); + + cur_qs = key; + + for (i = 0;; i++) { + switch (args_type[i]) { + case ',': + case '\0': + qdict_put(qdict, qstring_get_str(key), type); + QDECREF(key); + if (args_type[i] == '\0') { + goto out; + } + type = qstring_new(); /* qdict has ref */ + cur_qs = key = qstring_new(); + break; + case ':': + cur_qs = type; + break; + default: + qstring_append_chr(cur_qs, args_type[i]); + break; + } + } + +out: + return qdict; +} + +/* + * Client argument checking rules: + * + * 1. Client must provide all mandatory arguments + */ +static int qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args) +{ + int flags, err; + QDict *cmd_args; + + cmd_args = qdict_from_args_type(cmd->args_type); + + flags = 0; + err = check_mandatory_args(cmd_args, client_args, &flags); + if (err) { + goto out; + } + + /* TODO: Check client args type */ + +out: + QDECREF(cmd_args); + return err; +} + static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { int err; @@ -4210,6 +4311,11 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) QDECREF(input); + err = qmp_check_client_args(cmd, args); + if (err < 0) { + goto err_out; + } + err = monitor_check_qmp_args(cmd, args); if (err < 0) { goto err_out;