From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886714735575.4009360150546; Thu, 23 Feb 2017 13:51:54 -0800 (PST) Received: from localhost ([::1]:33059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Il-0005DV-Fl for importer@patchew.org; Thu, 23 Feb 2017 16:51:51 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34778) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CV-0007l3-Vp for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CS-0004ad-RB for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46554) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CS-0004aI-LF for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:20 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BD8AE3A7697; Thu, 23 Feb 2017 21:45:20 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjJAM003284 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 23 Feb 2017 16:45:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id BB5B9113864A; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:44:57 +0100 Message-Id: <1487886317-27400-2-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 23 Feb 2017 21:45:20 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 01/21] qga: Fix crash on non-dictionary QMP argument X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The value of key 'arguments' must be a JSON object. qemu-ga neglects to check, and crashes. To reproduce, send { 'execute': 'guest-sync', 'arguments': [] } to qemu-ga. do_qmp_dispatch() uses qdict_get_qdict() to get the arguments. When not a JSON object, this gets a null pointer, which flows through the generated marshalling function to qobject_input_visitor_new(), where it fails the assertion. qmp_dispatch_check_obj() needs to catch this error. QEMU isn't affected, because it runs qmp_check_input_obj() first, which basically duplicates qmp_check_input_obj()'s checks, plus the missing one. Fix by copying the missing one from qmp_check_input_obj() to qmp_dispatch_check_obj(). Signed-off-by: Markus Armbruster Cc: Michael Roth Reviewed-by: Eric Blake --- qapi/qmp-dispatch.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 48bec20..621922f 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -47,7 +47,13 @@ static QDict *qmp_dispatch_check_obj(const QObject *requ= est, Error **errp) return NULL; } has_exec_key =3D true; - } else if (strcmp(arg_name, "arguments")) { + } else if (!strcmp(arg_name, "arguments")) { + if (qobject_type(arg_obj) !=3D QTYPE_QDICT) { + error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, + "arguments", "object"); + return NULL; + } + } else { error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name); return NULL; } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886725154863.1443029584606; Thu, 23 Feb 2017 13:52:05 -0800 (PST) Received: from localhost ([::1]:33062 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Ix-0005M7-Sy for importer@patchew.org; Thu, 23 Feb 2017 16:52:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34782) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CV-0007l7-W1 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CS-0004ab-RU for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59060) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CS-0004a7-LJ for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:20 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A520D85542 for ; Thu, 23 Feb 2017 21:45:20 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7074F2D653 for ; Thu, 23 Feb 2017 21:45:20 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id BF0F5113864D; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:44:58 +0100 Message-Id: <1487886317-27400-3-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 23 Feb 2017 21:45:20 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 02/21] libqtest: Work around a "QMP wants a newline" bug X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The next commit is going to add a test that calls qmp("null"). Curiously, this hangs. Here's why. qmp_fd_sendv() doesn't send newlines. Not even when @fmt contains some. At first glance, the QMP parser seems to be fine with that. However, it turns out that it fails to react to input until it sees either a newline, an object or an array. To reproduce, feed to a QMP monitor like this: $ echo -n 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "pa= ckage": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}} No output after the greeting. Add a newline: $ echo 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "pa= ckage": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}} {"error": {"class": "GenericError", "desc": "Expected 'object' in QMP i= nput"}} Correct output for input 'null'. Add an object instead: $ echo -n 'null { "execute": "qmp_capabilities" }' | socat UNIX:qmp-soc= ket STDIO {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "pa= ckage": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}} {"error": {"class": "GenericError", "desc": "Expected 'object' in QMP i= nput"}} {"return": {}} Also correct output. Work around this QMP bug by having qmp_fd_sendv() append a newline. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- tests/libqtest.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index e54354d..ad23ce9 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -442,14 +442,20 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) if (qobj) { int log =3D getenv("QTEST_LOG") !=3D NULL; QString *qstr =3D qobject_to_json(qobj); - const char *str =3D qstring_get_str(qstr); - size_t size =3D qstring_get_length(qstr); + const char *str; + + /* + * BUG: QMP doesn't react to input until it sees a newline, an + * object, or an array. Work-around: give it a newline. + */ + qstring_append_chr(qstr, '\n'); + str =3D qstring_get_str(qstr); =20 if (log) { fprintf(stderr, "%s", str); } /* Send QMP request */ - socket_send(fd, str, size); + socket_send(fd, str, qstring_get_length(qstr)); =20 QDECREF(qstr); qobject_decref(qobj); --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148788645494854.385263112186976; Thu, 23 Feb 2017 13:47:34 -0800 (PST) Received: from localhost ([::1]:33038 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Eb-00019F-KO for importer@patchew.org; Thu, 23 Feb 2017 16:47:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34784) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CW-0007l8-00 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CT-0004ay-57 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59046) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CS-0004aP-Sp for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:21 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0B74C3D945 for ; Thu, 23 Feb 2017 21:45:21 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjJYA018945 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C14F41138650; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:44:59 +0100 Message-Id: <1487886317-27400-4-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 23 Feb 2017 21:45:21 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 03/21] qmp-test: New, covering basic QMP protocol X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- tests/Makefile.include | 5 +- tests/libqtest.c | 17 ++++-- tests/libqtest.h | 8 +++ tests/qmp-test.c | 139 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 tests/qmp-test.c diff --git a/tests/Makefile.include b/tests/Makefile.include index e60bb6c..b212150 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -133,7 +133,9 @@ check-block-$(CONFIG_POSIX) +=3D tests/qemu-iotests-qui= ck.sh # All QTests for now are POSIX-only, but the dependencies are # really in libqtest, not in the testcases themselves. =20 -check-qtest-generic-y =3D tests/device-introspect-test$(EXESUF) +check-qtest-generic-y =3D tests/qmp-test$(EXESUF) +gcov-files-generic-y =3D monitor.c qapi/qmp-dispatch.c +check-qtest-generic-y +=3D tests/device-introspect-test$(EXESUF) gcov-files-generic-y =3D qdev-monitor.c qmp.c =20 gcov-files-ipack-y +=3D hw/ipack/ipack.c @@ -654,6 +656,7 @@ libqos-imx-obj-y =3D $(libqos-obj-y) tests/libqos/i2c-i= mx.o libqos-usb-obj-y =3D $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos= /usb.o libqos-virtio-obj-y =3D $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/lib= qos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/lib= qos/malloc-generic.o =20 +tests/qmp-test$(EXESUF): tests/qmp-test.o tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o diff --git a/tests/libqtest.c b/tests/libqtest.c index ad23ce9..cf27afc 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -149,7 +149,7 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *d= ata) g_hook_prepend(&abrt_hooks, hook); } =20 -QTestState *qtest_init(const char *extra_args) +QTestState *qtest_init_without_qmp_handshake(const char *extra_args) { QTestState *s; int sock, qmpsock, i; @@ -204,10 +204,6 @@ QTestState *qtest_init(const char *extra_args) s->irq_level[i] =3D false; } =20 - /* Read the QMP greeting and then do the handshake */ - qtest_qmp_discard_response(s, ""); - qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); - if (getenv("QTEST_STOP")) { kill(s->qemu_pid, SIGSTOP); } @@ -219,6 +215,17 @@ QTestState *qtest_init(const char *extra_args) return s; } =20 +QTestState *qtest_init(const char *extra_args) +{ + QTestState *s =3D qtest_init_without_qmp_handshake(extra_args); + + /* Read the QMP greeting and then do the handshake */ + qtest_qmp_discard_response(s, ""); + qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); + + return s; +} + void qtest_quit(QTestState *s) { qtest_instances =3D g_list_remove(qtest_instances, s); diff --git a/tests/libqtest.h b/tests/libqtest.h index 90f182e..23bd76c 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -32,6 +32,14 @@ extern QTestState *global_qtest; QTestState *qtest_init(const char *extra_args); =20 /** + * qtest_init: + * @extra_args: other arguments to pass to QEMU. + * + * Returns: #QTestState instance. + */ +QTestState *qtest_init_without_qmp_handshake(const char *extra_args); + +/** * qtest_quit: * @s: #QTestState instance to operate on. * diff --git a/tests/qmp-test.c b/tests/qmp-test.c new file mode 100644 index 0000000..405e49e --- /dev/null +++ b/tests/qmp-test.c @@ -0,0 +1,139 @@ +/* + * QMP protocol test cases + * + * Copyright (c) 2017 Red Hat Inc. + * + * Authors: + * Markus Armbruster , + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qapi-visit.h" +#include "qapi/error.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/visitor.h" + +const char common_args[] =3D "-nodefaults -machine none"; + +static const char *get_error_class(QDict *resp) +{ + QDict *error =3D qdict_get_qdict(resp, "error"); + const char *desc =3D qdict_get_try_str(error, "desc"); + + g_assert(desc); + return error ? qdict_get_try_str(error, "class") : NULL; +} + +static void test_version(QObject *version) +{ + Visitor *v; + VersionInfo *vinfo; + + g_assert(version); + v =3D qobject_input_visitor_new(version, true); + visit_type_VersionInfo(v, "version", &vinfo, &error_abort); + qapi_free_VersionInfo(vinfo); + visit_free(v); +} + +static void test_malformed(void) +{ + QDict *resp; + + /* Not even a dictionary */ + resp =3D qmp("null"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + QDECREF(resp); + + /* No "execute" key */ + resp =3D qmp("{}"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + QDECREF(resp); + + /* "execute" isn't a string */ + resp =3D qmp("{ 'execute': true }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + QDECREF(resp); + + /* "arguments" isn't a dictionary */ + resp =3D qmp("{ 'execute': 'no-such-cmd', 'arguments': [] }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + QDECREF(resp); + + /* extra key */ + resp =3D qmp("{ 'execute': 'no-such-cmd', 'extra': true }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + QDECREF(resp); +} + +static void test_qmp_protocol(void) +{ + QDict *resp, *q, *ret; + QList *capabilities; + + global_qtest =3D qtest_init_without_qmp_handshake(common_args); + + /* Test greeting */ + resp =3D qmp_receive(); + q =3D qdict_get_qdict(resp, "QMP"); + g_assert(q); + test_version(qdict_get(q, "version")); + capabilities =3D qdict_get_qlist(q, "capabilities"); + g_assert(capabilities && qlist_empty(capabilities)); + QDECREF(resp); + + /* Test valid command before handshake */ + resp =3D qmp("{ 'execute': 'query-version' }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); + QDECREF(resp); + + /* Test malformed commands before handshake */ + test_malformed(); + + /* Test handshake */ + resp =3D qmp("{ 'execute': 'qmp_capabilities' }"); + ret =3D qdict_get_qdict(resp, "return"); + g_assert(ret && !qdict_size(ret)); + QDECREF(resp); + + /* Test repeated handshake */ + resp =3D qmp("{ 'execute': 'qmp_capabilities' }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); + QDECREF(resp); + + /* Test valid command */ + resp =3D qmp("{ 'execute': 'query-version' }"); + test_version(qdict_get(resp, "return")); + QDECREF(resp); + + /* Test malformed commands */ + test_malformed(); + + /* Test 'id' */ + resp =3D qmp("{ 'execute': 'query-name', 'id': 'cookie#1' }"); + ret =3D qdict_get_qdict(resp, "return"); + g_assert(ret); + g_assert_cmpstr(qdict_get_try_str(resp, "id"), =3D=3D, "cookie#1"); + QDECREF(resp); + + /* Test command failure with 'id' */ + resp =3D qmp("{ 'execute': 'human-monitor-command', 'id': 2 }"); + g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); + g_assert_cmpint(qdict_get_int(resp, "id"), =3D=3D, 2); + QDECREF(resp); + + qtest_end(); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("qmp/protocol", test_qmp_protocol); + + return g_test_run(); +} --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886719718127.50455269587269; Thu, 23 Feb 2017 13:51:59 -0800 (PST) Received: from localhost ([::1]:33060 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Is-0005HD-EU for importer@patchew.org; Thu, 23 Feb 2017 16:51:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34781) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CV-0007l6-Vn for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CT-0004ar-3I for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39912) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CS-0004aN-RM for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:21 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 050014E4C5 for ; Thu, 23 Feb 2017 21:45:21 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjJO9003286 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C44431138657; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:00 +0100 Message-Id: <1487886317-27400-5-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 23 Feb 2017 21:45:21 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 04/21] qmp: Dumb down how we run QMP command registration X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The way we get QMP commands registered is high tech: * qapi-commands.py generates qmp_init_marshal() that does the actual work * it also generates the magic to register it as a MODULE_INIT_QAPI function, so it runs when someone calls module_call_init(MODULE_INIT_QAPI) * main() calls module_call_init() QEMU needs to register a few non-qapified commands. Same high tech works: monitor.c has its own qmp_init_marshal() along with the magic to make it run in module_call_init(MODULE_INIT_QAPI). QEMU also needs to unregister commands that are not wanted in this build's configuration (commit 5032a16). Simple enough: qmp_unregister_commands_hack(). The difficulty is to make it run after the generated qmp_init_marshal(). We can't simply run it in monitor.c's qmp_init_marshal(), because the order in which the registered functions run is indeterminate. So qmp_init_marshal() registers qmp_init_marshal() separately. Since registering *appends* to the list of registered functions, this will make it run after all the functions that have been registered already. I suspect it takes a long and expensive computer science education to not find this silly. Dumb it down as follows: * Drop MODULE_INIT_QAPI entirely * Give the generated qmp_init_marshal() external linkage. * Call it instead of module_call_init(MODULE_INIT_QAPI) * Except in QEMU proper, call new monitor_init_qmp_commands() that in turn calls the generated qmp_init_marshal(), registers the additional commands and unregisters the unwanted ones. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/monitor/monitor.h | 1 + include/qemu/module.h | 2 -- monitor.c | 9 ++++----- qga/main.c | 2 +- scripts/qapi-commands.py | 5 ++--- tests/test-qmp-commands.c | 2 +- vl.c | 2 +- 7 files changed, 10 insertions(+), 13 deletions(-) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index e64b944..d2b3aaf 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -16,6 +16,7 @@ extern Monitor *cur_mon; =20 bool monitor_cur_is_qmp(void); =20 +void monitor_init_qmp_commands(void); void monitor_init(Chardev *chr, int flags); void monitor_cleanup(void); =20 diff --git a/include/qemu/module.h b/include/qemu/module.h index 877cca7..56dd218 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -42,7 +42,6 @@ static void __attribute__((constructor)) do_qemu_init_ ##= function(void) \ typedef enum { MODULE_INIT_BLOCK, MODULE_INIT_OPTS, - MODULE_INIT_QAPI, MODULE_INIT_QOM, MODULE_INIT_TRACE, MODULE_INIT_MAX @@ -50,7 +49,6 @@ typedef enum { =20 #define block_init(function) module_init(function, MODULE_INIT_BLOCK) #define opts_init(function) module_init(function, MODULE_INIT_OPTS) -#define qapi_init(function) module_init(function, MODULE_INIT_QAPI) #define type_init(function) module_init(function, MODULE_INIT_QOM) #define trace_init(function) module_init(function, MODULE_INIT_TRACE) =20 diff --git a/monitor.c b/monitor.c index 56867e8..5be71d6 100644 --- a/monitor.c +++ b/monitor.c @@ -995,8 +995,10 @@ static void qmp_unregister_commands_hack(void) #endif } =20 -static void qmp_init_marshal(void) +void monitor_init_qmp_commands(void) { + qmp_init_marshal(); + qmp_register_command("query-qmp-schema", qmp_query_qmp_schema, QCO_NO_OPTIONS); qmp_register_command("device_add", qmp_device_add, @@ -1004,12 +1006,9 @@ static void qmp_init_marshal(void) qmp_register_command("netdev_add", qmp_netdev_add, QCO_NO_OPTIONS); =20 - /* call it after the rest of qapi_init() */ - register_module_init(qmp_unregister_commands_hack, MODULE_INIT_QAPI); + qmp_unregister_commands_hack(); } =20 -qapi_init(qmp_init_marshal); - /* set the current CPU defined by the user */ int monitor_set_cpu(int cpu_index) { diff --git a/qga/main.c b/qga/main.c index 538e4ee..6f8c614 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1321,7 +1321,7 @@ int main(int argc, char **argv) =20 config->log_level =3D G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL; =20 - module_call_init(MODULE_INIT_QAPI); + qmp_init_marshal(); =20 init_dfl_pathnames(); config_load(config); diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 09e8467..a75946f 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -208,14 +208,12 @@ def gen_register_command(name, success_response): def gen_registry(registry): ret =3D mcgen(''' =20 -static void qmp_init_marshal(void) +void qmp_init_marshal(void) { ''') ret +=3D registry ret +=3D mcgen(''' } - -qapi_init(qmp_init_marshal); ''') return ret =20 @@ -308,6 +306,7 @@ fdecl.write(mcgen(''' #include "qapi/qmp/qdict.h" #include "qapi/error.h" =20 +void qmp_init_marshal(void); ''', prefix=3Dprefix)) =20 diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index ff94481..c4e20d1 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -273,7 +273,7 @@ int main(int argc, char **argv) g_test_add_func("/0.15/dealloc_types", test_dealloc_types); g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial); =20 - module_call_init(MODULE_INIT_QAPI); + qmp_init_marshal(); g_test_run(); =20 return 0; diff --git a/vl.c b/vl.c index b5d0a19..a0634b0 100644 --- a/vl.c +++ b/vl.c @@ -2966,7 +2966,7 @@ int main(int argc, char **argv, char **envp) qemu_init_exec_dir(argv[0]); =20 module_call_init(MODULE_INIT_QOM); - module_call_init(MODULE_INIT_QAPI); + monitor_init_qmp_commands(); =20 qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887229353964.4472345355481; Thu, 23 Feb 2017 14:00:29 -0800 (PST) Received: from localhost ([::1]:33103 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1R6-0006VF-3O for importer@patchew.org; Thu, 23 Feb 2017 17:00:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34794) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CW-0007lB-29 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bs-Ix for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41254) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bA-AI for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6FEFAC04B30F for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0D16C2D653 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C747311386CE; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:01 +0100 Message-Id: <1487886317-27400-6-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 05/21] qmp: Clean up how we enforce capability negotiation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" To enforce capability negotiation before normal operation, handle_qmp_command() inspects every command before it's handed off to qmp_dispatch(). This is a bit of a layering violation, and results in duplicated code. Before capability negotiation (!cur_mon->in_command_mode), we fail commands other than "qmp_capabilities". This is what enforces capability negotiation. Afterwards, we fail command "qmp_capabilities". Clean this up as follows. The obvious place to fail a command is the command itself, so move the "afterwards" check to qmp_qmp_capabilities(). We do the "before" check in every other command, but that would be bothersome. Instead, start without all the other commands, by registering only qmp_qmp_capabilities(). Register the others in qmp_qmp_capabilities(). Additionally, replace the generic human-readable error message for CommandNotFound by one that reminds the user to run qmp_capabilities. Without that, we'd regress commit 2d5a834. Signed-off-by: Markus Armbruster --- monitor.c | 70 ++++++++++++++++++++++++++++++++++++-----------------------= ---- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/monitor.c b/monitor.c index 5be71d6..dcf2de7 100644 --- a/monitor.c +++ b/monitor.c @@ -563,11 +563,6 @@ static void monitor_qapi_event_init(void) qmp_event_set_func_emit(monitor_qapi_event_queue); } =20 -void qmp_qmp_capabilities(Error **errp) -{ - cur_mon->qmp.in_command_mode =3D true; -} - static void handle_hmp_command(Monitor *mon, const char *cmdline); =20 static void monitor_data_init(Monitor *mon) @@ -995,7 +990,7 @@ static void qmp_unregister_commands_hack(void) #endif } =20 -void monitor_init_qmp_commands(void) +static void monitor_init_real_qmp_commands(void) { qmp_init_marshal(); =20 @@ -1009,6 +1004,32 @@ void monitor_init_qmp_commands(void) qmp_unregister_commands_hack(); } =20 +void monitor_init_qmp_commands(void) +{ + /* + * Start with just qmp_capabilities, to enforce capability + * negotiation. qmp_capabilities will register the other + * commands. See also the error message replacement hack in + * handle_qmp_command(). + */ + qmp_register_command("qmp_capabilities", + qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS); +} + +void qmp_qmp_capabilities(Error **errp) +{ + if (cur_mon->qmp.in_command_mode) { + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "Capabilities negotiation is already complete, command " + "ignored"); + return; + } + + cur_mon->qmp.in_command_mode =3D true; + qmp_unregister_command("qmp_capabilities"); + monitor_init_real_qmp_commands(); +} + /* set the current CPU defined by the user */ int monitor_set_cpu(int cpu_index) { @@ -3676,26 +3697,6 @@ static int monitor_can_read(void *opaque) return (mon->suspend_cnt =3D=3D 0) ? 1 : 0; } =20 -static bool invalid_qmp_mode(const Monitor *mon, const char *cmd, - Error **errp) -{ - bool is_cap =3D g_str_equal(cmd, "qmp_capabilities"); - - if (is_cap && mon->qmp.in_command_mode) { - error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, - "Capabilities negotiation is already complete, command " - "'%s' ignored", cmd); - return true; - } - if (!is_cap && !mon->qmp.in_command_mode) { - error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, - "Expecting capabilities negotiation with " - "'qmp_capabilities' before command '%s'", cmd); - return true; - } - return false; -} - /* * Input object checking rules * @@ -3781,12 +3782,21 @@ static void handle_qmp_command(JSONMessageParser *p= arser, GQueue *tokens) cmd_name =3D qdict_get_str(qdict, "execute"); trace_handle_qmp_command(mon, cmd_name); =20 - if (invalid_qmp_mode(mon, cmd_name, &err)) { - goto err_out; - } - rsp =3D qmp_dispatch(req); =20 + qdict =3D qdict_get_qdict(qobject_to_qdict(rsp), "error"); + if (qdict) { + if (!mon->qmp.in_command_mode + && !strcmp(qdict_get_try_str(qdict, "class"), + QapiErrorClass_lookup[ERROR_CLASS_COMMAND_NOT_FOUND= ])) { + /* Provide a more useful error message */ + qdict_del(qdict, "desc"); + qdict_put(qdict, "desc", + qstring_from_str("Expecting capabilities negotiation" + " with 'qmp_capabilities'")); + } + } + err_out: if (err) { qdict =3D qdict_new(); --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886975369221.94813743217617; Thu, 23 Feb 2017 13:56:15 -0800 (PST) Received: from localhost ([::1]:33082 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1N0-0001l3-7W for importer@patchew.org; Thu, 23 Feb 2017 16:56:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34790) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CW-0007lA-13 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bn-IX for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35286) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bD-AU for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 72EE7C054C42 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjL46017616 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CA22711386DC; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:02 +0100 Message-Id: <1487886317-27400-7-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 06/21] qmp: Drop duplicated QMP command object checks X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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: Markus Armbruster Reviewed-by: Eric Blake --- monitor.c | 74 +++++--------------------------------------------= ---- qapi/qmp-dispatch.c | 3 +-- trace-events | 1 - 3 files changed, 7 insertions(+), 71 deletions(-) diff --git a/monitor.c b/monitor.c index dcf2de7..d83888d 100644 --- a/monitor.c +++ b/monitor.c @@ -3697,67 +3697,10 @@ static int monitor_can_read(void *opaque) return (mon->suspend_cnt =3D=3D 0) ? 1 : 0; } =20 -/* - * 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 =3D 0; - QDict *input_dict; - - input_dict =3D qobject_to_qdict(input_obj); - if (!input_dict) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object"); - return NULL; - } - - - for (ent =3D qdict_first(input_dict); ent; ent =3D qdict_next(input_di= ct, ent)){ - const char *arg_name =3D qdict_entry_key(ent); - const QObject *arg_obj =3D qdict_entry_value(ent); - - if (!strcmp(arg_name, "execute")) { - if (qobject_type(arg_obj) !=3D QTYPE_QSTRING) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, - "execute", "string"); - return NULL; - } - has_exec_key =3D 1; - } else if (!strcmp(arg_name, "arguments")) { - if (qobject_type(arg_obj) !=3D 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 =3D NULL, *id =3D NULL; QDict *qdict =3D NULL; - const char *cmd_name; Monitor *mon =3D cur_mon; Error *err =3D NULL; =20 @@ -3770,17 +3713,12 @@ static void handle_qmp_command(JSONMessageParser *p= arser, GQueue *tokens) goto err_out; } =20 - qdict =3D qmp_check_input_obj(req, &err); - if (!qdict) { - goto err_out; - } - - id =3D qdict_get(qdict, "id"); - qobject_incref(id); - qdict_del(qdict, "id"); - - cmd_name =3D qdict_get_str(qdict, "execute"); - trace_handle_qmp_command(mon, cmd_name); + qdict =3D qobject_to_qdict(req); + if (qdict) { + id =3D qdict_get(qdict, "id"); + qobject_incref(id); + qdict_del(qdict, "id"); + } /* else will fail qmp_dispatch() */ =20 rsp =3D qmp_dispatch(req); =20 diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 621922f..4fc1122 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -30,8 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *reque= st, Error **errp) =20 dict =3D 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; } =20 diff --git a/trace-events b/trace-events index 7288557..b07a09b 100644 --- a/trace-events +++ b/trace-events @@ -65,7 +65,6 @@ xen_remap_bucket(uint64_t index) "index %#"PRIx64 xen_map_cache_return(void* ptr) "%p" =20 # 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=3D%d da= ta=3D%p" monitor_protocol_event_emit(uint32_t event, void *data) "event=3D%d data= =3D%p" monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "= event=3D%d data=3D%p rate=3D%" PRId64 --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887214306384.40649889840904; Thu, 23 Feb 2017 14:00:14 -0800 (PST) Received: from localhost ([::1]:33101 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Qr-0006IY-2W for importer@patchew.org; Thu, 23 Feb 2017 17:00:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34855) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CX-0007lT-GM for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bz-Kw for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46564) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bF-Dq for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 828273A76B3 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 217E92D654 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CCF6611385E0; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:03 +0100 Message-Id: <1487886317-27400-8-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 07/21] qmp: Eliminate silly QERR_QMP_* macros X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The QERR_ macros are leftovers from the days of "rich" error objects. QERR_QMP_BAD_INPUT_OBJECT, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, QERR_QMP_EXTRA_MEMBER are used in just one place now, except for one use that has crept into qobject-input-visitor.c. Drop these macros, to make the (bad) error messages more visible. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/qmp/qerror.h | 9 --------- qapi/qmp-dispatch.c | 13 +++++++------ qapi/qobject-input-visitor.c | 3 ++- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 6586c9f..c82360f 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -82,15 +82,6 @@ #define QERR_QGA_COMMAND_FAILED \ "Guest agent command failed, error was '%s'" =20 -#define QERR_QMP_BAD_INPUT_OBJECT \ - "Expected '%s' in QMP input" - -#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \ - "QMP input object member '%s' expects '%s'" - -#define QERR_QMP_EXTRA_MEMBER \ - "QMP input object member '%s' is unexpected" - #define QERR_SET_PASSWD_FAILED \ "Could not set password" =20 diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 4fc1122..377ebb5 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -30,7 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *reque= st, Error **errp) =20 dict =3D qobject_to_qdict(request); if (!dict) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "object"); + error_setg(errp, "Expected '%s' in QMP input", "object"); return NULL; } =20 @@ -41,25 +41,26 @@ static QDict *qmp_dispatch_check_obj(const QObject *req= uest, Error **errp) =20 if (!strcmp(arg_name, "execute")) { if (qobject_type(arg_obj) !=3D QTYPE_QSTRING) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execut= e", - "string"); + error_setg(errp, "QMP input object member '%s' expects '%s= '", + "execute", "string"); return NULL; } has_exec_key =3D true; } else if (!strcmp(arg_name, "arguments")) { if (qobject_type(arg_obj) !=3D QTYPE_QDICT) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, + error_setg(errp, "QMP input object member '%s' expects '%s= '", "arguments", "object"); return NULL; } } else { - error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name); + error_setg(errp, "QMP input object member '%s' is unexpected", + arg_name); return NULL; } } =20 if (!has_exec_key) { - error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute"); + error_setg(errp, "Expected '%s' in QMP input", "execute"); return NULL; } =20 diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 0063327..ed6c24c 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -140,7 +140,8 @@ static void qobject_input_check_struct(Visitor *v, Erro= r **errp) =20 g_hash_table_iter_init(&iter, top_ht); if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { - error_setg(errp, QERR_QMP_EXTRA_MEMBER, key); + error_setg(errp, "QMP input object member '%s' is unexpect= ed", + key); } } } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886964340609.9678289717425; Thu, 23 Feb 2017 13:56:04 -0800 (PST) Received: from localhost ([::1]:33080 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Mo-0001a7-47 for importer@patchew.org; Thu, 23 Feb 2017 16:56:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34788) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CW-0007l9-1B for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bb-GA for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59854) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004b5-A9 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6453061D26 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLxn003302 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CFCBA11385E1; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:04 +0100 Message-Id: <1487886317-27400-9-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 08/21] qmp: Improve QMP dispatch error messages X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/qmp-dispatch.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 377ebb5..4610b6d 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -30,7 +30,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *reque= st, Error **errp) =20 dict =3D qobject_to_qdict(request); if (!dict) { - error_setg(errp, "Expected '%s' in QMP input", "object"); + error_setg(errp, "QMP input must be a JSON object"); return NULL; } =20 @@ -41,15 +41,17 @@ static QDict *qmp_dispatch_check_obj(const QObject *req= uest, Error **errp) =20 if (!strcmp(arg_name, "execute")) { if (qobject_type(arg_obj) !=3D QTYPE_QSTRING) { - error_setg(errp, "QMP input object member '%s' expects '%s= '", - "execute", "string"); + error_setg(errp, + "QMP input object member '%s' must be %s", + "execute", "a string"); return NULL; } has_exec_key =3D true; } else if (!strcmp(arg_name, "arguments")) { if (qobject_type(arg_obj) !=3D QTYPE_QDICT) { - error_setg(errp, "QMP input object member '%s' expects '%s= '", - "arguments", "object"); + error_setg(errp, + "QMP input object member '%s' must be %s", + "arguments", "an object"); return NULL; } } else { @@ -60,7 +62,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *reque= st, Error **errp) } =20 if (!has_exec_key) { - error_setg(errp, "Expected '%s' in QMP input", "execute"); + error_setg(errp, "QMP input object lacks key 'execute'"); return NULL; } =20 --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886450737315.5278327258742; Thu, 23 Feb 2017 13:47:30 -0800 (PST) Received: from localhost ([::1]:33037 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1EW-0000r9-EG for importer@patchew.org; Thu, 23 Feb 2017 16:47:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34780) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CV-0007l5-Vh for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bV-FM for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59856) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004b7-8i for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6533061E7B for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLjs030170 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D2C0311385ED; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:05 +0100 Message-Id: <1487886317-27400-10-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 09/21] qapi: Improve a QObject input visitor error message X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The QObject input visitor has three error message formats: * Parameter '%s' is missing * "Invalid parameter type for '%s', expected: %s" * "QMP input object member '%s' is unexpected" The '%s' are member names (or "null", but I'll fix that later). The last error message calls the thing "QMP input object member" instead of "parameter". Misleading when the visitor is used on QObjects that don't come from QMP. Change it to "Parameter '%s' is unexpected". Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/qobject-input-visitor.c | 3 +-- tests/test-qga.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index ed6c24c..f3b6713 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -140,8 +140,7 @@ static void qobject_input_check_struct(Visitor *v, Erro= r **errp) =20 g_hash_table_iter_init(&iter, top_ht); if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { - error_setg(errp, "QMP input object member '%s' is unexpect= ed", - key); + error_setg(errp, "Parameter '%s' is unexpected", key); } } } diff --git a/tests/test-qga.c b/tests/test-qga.c index 868b02a..ae97b57 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -213,7 +213,7 @@ static void test_qga_invalid_args(gconstpointer fix) desc =3D qdict_get_try_str(error, "desc"); =20 g_assert_cmpstr(class, =3D=3D, "GenericError"); - g_assert_cmpstr(desc, =3D=3D, "QMP input object member 'foo' is unexpe= cted"); + g_assert_cmpstr(desc, =3D=3D, "Parameter 'foo' is unexpected"); =20 QDECREF(ret); } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 14878869762221014.8176007132071; Thu, 23 Feb 2017 13:56:16 -0800 (PST) Received: from localhost ([::1]:33083 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1N0-0001mD-T2 for importer@patchew.org; Thu, 23 Feb 2017 16:56:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34777) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CV-0007l2-V0 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004bg-GP for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60180) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004b9-AZ for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6D6A27E9D7 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLSs003304 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D59D911385F0; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:06 +0100 Message-Id: <1487886317-27400-11-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 10/21] qapi: Clean up after commit 3d344c2 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Drop unused QIV_STACK_SIZE and unused qobject_input_start_struct() parameter errp. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/qobject-input-visitor.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index f3b6713..2c2f883 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -21,8 +21,6 @@ #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" =20 -#define QIV_STACK_SIZE 1024 - typedef struct StackObject { QObject *obj; /* Object being visited */ @@ -103,8 +101,7 @@ static void qdict_add_key(const char *key, QObject *obj= , void *opaque) } =20 static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, - QObject *obj, void *qapi, - Error **errp) + QObject *obj, void *qapi) { GHashTable *h; StackObject *tos =3D g_new0(StackObject, 1); @@ -170,7 +167,6 @@ static void qobject_input_start_struct(Visitor *v, cons= t char *name, void **obj, { QObjectInputVisitor *qiv =3D to_qiv(v); QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - Error *err =3D NULL; =20 if (obj) { *obj =3D NULL; @@ -184,11 +180,7 @@ static void qobject_input_start_struct(Visitor *v, con= st char *name, void **obj, return; } =20 - qobject_input_push(qiv, qobj, obj, &err); - if (err) { - error_propagate(errp, err); - return; - } + qobject_input_push(qiv, qobj, obj); =20 if (obj) { *obj =3D g_malloc0(size); @@ -216,7 +208,7 @@ static void qobject_input_start_list(Visitor *v, const = char *name, return; } =20 - entry =3D qobject_input_push(qiv, qobj, list, errp); + entry =3D qobject_input_push(qiv, qobj, list); if (list) { if (entry) { *list =3D g_malloc0(size); --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148788672503517.35004085524963; Thu, 23 Feb 2017 13:52:05 -0800 (PST) Received: from localhost ([::1]:33061 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Iw-0005Lg-RU for importer@patchew.org; Thu, 23 Feb 2017 16:52:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34844) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CX-0007lF-4s for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CV-0004cQ-6Q for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49218) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CV-0004bR-0l for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 12140811AC for ; Thu, 23 Feb 2017 21:45:23 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLMO018960 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D919C11385FC; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:07 +0100 Message-Id: <1487886317-27400-12-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 23 Feb 2017 21:45:23 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 11/21] qapi: Make QObject input visitor set *list reliably X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" qobject_input_start_struct() sets *list, except when it fails because qobject_input_get_object() fails, i.e. the input object doesn't exist. All the other input visitor start_struct(), start_list(), start_alternate() always set *obj / *list. Change qobject_input_start_struct() to match. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/qobject-input-visitor.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 2c2f883..d58696c 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -196,25 +196,21 @@ static void qobject_input_start_list(Visitor *v, cons= t char *name, QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); const QListEntry *entry; =20 + if (list) { + *list =3D NULL; + } if (!qobj) { return; } if (qobject_type(qobj) !=3D QTYPE_QLIST) { - if (list) { - *list =3D NULL; - } error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "list"); return; } =20 entry =3D qobject_input_push(qiv, qobj, list); - if (list) { - if (entry) { - *list =3D g_malloc0(size); - } else { - *list =3D NULL; - } + if (entry && list) { + *list =3D g_malloc0(size); } } =20 --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887484261830.2752681793673; Thu, 23 Feb 2017 14:04:44 -0800 (PST) Received: from localhost ([::1]:33124 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1VB-0002b0-Tf for importer@patchew.org; Thu, 23 Feb 2017 17:04:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34931) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CZ-0007mc-9N for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CV-0004cK-4r for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46568) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bO-Sj for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0AB301555A for ; Thu, 23 Feb 2017 21:45:23 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLDm018964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DBED71138604; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:08 +0100 Message-Id: <1487886317-27400-13-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 23 Feb 2017 21:45:23 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 12/21] qapi: Improve qobject input visitor error reporting X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Error messages refer to nodes of the QObject being visited by name. Trouble is the names are sometimes less than helpful: * The name of the root QObject is whatever @name argument got passed to the visitor, except NULL gets mapped to "null". We commonly pass NULL. Not good. Avoiding errors "at the root" mitigates. For instance, visit_start_struct() can only fail when the visited object is not a dictionary, and we commonly ensure it is beforehand. * The name of a QDict's member is the member key. Good enough only when this happens to be unique. * The name of a QList's member is "null". Not good. Improve error messages by referring to nodes by path instead, as follows: * The path of the root QObject is whatever @name argument got passed to the visitor, except NULL gets mapped to "". * The path of a root QDict's member is the member key. * The path of a root QList's member is "[%zu]", where %zu is the list index, starting at zero. * The path of a non-root QDict's member is the path of the QDict concatenated with "." and the member key. * The path of a non-root QList's member is the path of the QList concatenated with "[%zu]", where %zu is the list index. For example, the incorrect QMP command { "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver= ": "raw", "file": {"driver": "file" } } } now fails with {"error": {"class": "GenericError", "desc": "Parameter 'file.filename' = is missing"}} instead of {"error": {"class": "GenericError", "desc": "Parameter 'filename' is mi= ssing"}} and { "execute": "input-send-event", "arguments": { "device": "bar", "event= s": [ [] ] } } now fails with {"error": {"class": "GenericError", "desc": "Invalid parameter type for= 'events[0]', expected: object"}} instead of {"error": {"class": "GenericError", "desc": "Invalid parameter type for= 'null', expected: QDict"}} Aside: calling the thing "parameter" is suboptimal for QMP, because the root object is "arguments" there. The qobject output visitor doesn't have this problem because it should not fail. Same for dealloc and clone visitors. The string visitors don't have this problem because they visit just one value, whose name needs to be passed to the visitor as @name. The string output visitor shouldn't fail anyway. The options visitor uses QemuOpts names. Their name space is flat, so the use of QDict member keys as names is fine. NULL names used with roots and lists could conceivably result in bad error messages. Left for another day. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/visitor.h | 6 --- qapi/qobject-input-visitor.c | 121 +++++++++++++++++++++++++++++++--------= ---- 2 files changed, 87 insertions(+), 40 deletions(-) diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 9bb6cba..7c91a50 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -66,12 +66,6 @@ * object, @name is the key associated with the value; and when * visiting a member of a list, @name is NULL. * - * FIXME: Clients must pass NULL for @name when visiting a member of a - * list, but this leads to poor error messages; it might be nicer to - * require a non-NULL name such as "key.0" for '{ "key": [ "value" ] - * }' if an error is encountered on "value" (or to have the visitor - * core auto-generate the nicer name). - * * The visit_type_FOO() functions expect a non-null @obj argument; * they allocate *@obj during input visits, leave it unchanged on * output visits, and recursively free any resources during a dealloc diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index d58696c..8015a98 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -21,19 +21,19 @@ #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" =20 -typedef struct StackObject -{ - QObject *obj; /* Object being visited */ +typedef struct StackObject { + const char *name; /* Name of @obj in its parent, if any */ + QObject *obj; /* QDict or QList being visited */ void *qapi; /* sanity check that caller uses same pointer */ =20 - GHashTable *h; /* If obj is dict: unvisited keys */ - const QListEntry *entry; /* If obj is list: unvisited tail */ + GHashTable *h; /* If @obj is QDict: unvisited keys */ + const QListEntry *entry; /* If @obj is QList: unvisited tail */ + unsigned index; /* If @obj is QList: list index of @entry = */ =20 - QSLIST_ENTRY(StackObject) node; + QSLIST_ENTRY(StackObject) node; /* parent */ } StackObject; =20 -struct QObjectInputVisitor -{ +struct QObjectInputVisitor { Visitor visitor; =20 /* Root of visit at visitor creation. */ @@ -45,6 +45,8 @@ struct QObjectInputVisitor =20 /* True to reject parse in visit_end_struct() if unvisited keys remain= . */ bool strict; + + GString *errname; /* Accumulator for full_name() */ }; =20 static QObjectInputVisitor *to_qiv(Visitor *v) @@ -52,9 +54,42 @@ static QObjectInputVisitor *to_qiv(Visitor *v) return container_of(v, QObjectInputVisitor, visitor); } =20 -static QObject *qobject_input_get_object(QObjectInputVisitor *qiv, - const char *name, - bool consume, Error **errp) +static const char *full_name(QObjectInputVisitor *qiv, const char *name) +{ + StackObject *so; + char buf[32]; + + if (qiv->errname) { + g_string_truncate(qiv->errname, 0); + } else { + qiv->errname =3D g_string_new(""); + } + + QSLIST_FOREACH(so , &qiv->stack, node) { + if (qobject_type(so->obj) =3D=3D QTYPE_QDICT) { + g_string_prepend(qiv->errname, name); + g_string_prepend_c(qiv->errname, '.'); + } else { + snprintf(buf, sizeof(buf), "[%u]", so->index); + g_string_prepend(qiv->errname, buf); + } + name =3D so->name; + } + + if (name) { + g_string_prepend(qiv->errname, name); + } else if (qiv->errname->str[0] =3D=3D '.') { + g_string_erase(qiv->errname, 0, 1); + } else { + return ""; + } + + return qiv->errname->str; +} + +static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv, + const char *name, + bool consume) { StackObject *tos; QObject *qobj; @@ -78,9 +113,6 @@ static QObject *qobject_input_get_object(QObjectInputVis= itor *qiv, bool removed =3D g_hash_table_remove(tos->h, name); assert(removed); } - if (!ret) { - error_setg(errp, QERR_MISSING_PARAMETER, name); - } } else { assert(qobject_type(qobj) =3D=3D QTYPE_QLIST); assert(!name); @@ -88,12 +120,25 @@ static QObject *qobject_input_get_object(QObjectInputV= isitor *qiv, assert(ret); if (consume) { tos->entry =3D qlist_next(tos->entry); + tos->index++; } } =20 return ret; } =20 +static QObject *qobject_input_get_object(QObjectInputVisitor *qiv, + const char *name, + bool consume, Error **errp) +{ + QObject *obj =3D qobject_input_try_get_object(qiv, name, consume); + + if (!obj) { + error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name)); + } + return obj; +} + static void qdict_add_key(const char *key, QObject *obj, void *opaque) { GHashTable *h =3D opaque; @@ -101,12 +146,14 @@ static void qdict_add_key(const char *key, QObject *o= bj, void *opaque) } =20 static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, + const char *name, QObject *obj, void *qapi) { GHashTable *h; StackObject *tos =3D g_new0(StackObject, 1); =20 assert(obj); + tos->name =3D name; tos->obj =3D obj; tos->qapi =3D qapi; =20 @@ -116,6 +163,7 @@ static const QListEntry *qobject_input_push(QObjectInpu= tVisitor *qiv, tos->h =3D h; } else if (qobject_type(obj) =3D=3D QTYPE_QLIST) { tos->entry =3D qlist_first(qobject_to_qlist(obj)); + tos->index =3D -1; } =20 QSLIST_INSERT_HEAD(&qiv->stack, tos, node); @@ -137,7 +185,8 @@ static void qobject_input_check_struct(Visitor *v, Erro= r **errp) =20 g_hash_table_iter_init(&iter, top_ht); if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { - error_setg(errp, "Parameter '%s' is unexpected", key); + error_setg(errp, "Parameter '%s' is unexpected", + full_name(qiv, key)); } } } @@ -175,12 +224,12 @@ static void qobject_input_start_struct(Visitor *v, co= nst char *name, void **obj, return; } if (qobject_type(qobj) !=3D QTYPE_QDICT) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "QDict"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "object"); return; } =20 - qobject_input_push(qiv, qobj, obj); + qobject_input_push(qiv, name, qobj, obj); =20 if (obj) { *obj =3D g_malloc0(size); @@ -203,12 +252,12 @@ static void qobject_input_start_list(Visitor *v, cons= t char *name, return; } if (qobject_type(qobj) !=3D QTYPE_QLIST) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "list"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "array"); return; } =20 - entry =3D qobject_input_push(qiv, qobj, list); + entry =3D qobject_input_push(qiv, name, qobj, list); if (entry && list) { *list =3D g_malloc0(size); } @@ -258,8 +307,8 @@ static void qobject_input_type_int64(Visitor *v, const = char *name, int64_t *obj, } qint =3D qobject_to_qint(qobj); if (!qint) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "integer"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "integer"); return; } =20 @@ -279,8 +328,8 @@ static void qobject_input_type_uint64(Visitor *v, const= char *name, } qint =3D qobject_to_qint(qobj); if (!qint) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "integer"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "integer"); return; } =20 @@ -299,8 +348,8 @@ static void qobject_input_type_bool(Visitor *v, const c= har *name, bool *obj, } qbool =3D qobject_to_qbool(qobj); if (!qbool) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "boolean"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "boolean"); return; } =20 @@ -320,8 +369,8 @@ static void qobject_input_type_str(Visitor *v, const ch= ar *name, char **obj, } qstr =3D qobject_to_qstring(qobj); if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "string"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); return; } =20 @@ -351,8 +400,8 @@ static void qobject_input_type_number(Visitor *v, const= char *name, double *obj, return; } =20 - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "number"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "number"); } =20 static void qobject_input_type_any(Visitor *v, const char *name, QObject *= *obj, @@ -380,15 +429,15 @@ static void qobject_input_type_null(Visitor *v, const= char *name, Error **errp) } =20 if (qobject_type(qobj) !=3D QTYPE_QNULL) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "null"); + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "null"); } } =20 static void qobject_input_optional(Visitor *v, const char *name, bool *pre= sent) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, false, NULL); + QObject *qobj =3D qobject_input_try_get_object(qiv, name, false); =20 if (!qobj) { *present =3D false; @@ -401,6 +450,7 @@ static void qobject_input_optional(Visitor *v, const ch= ar *name, bool *present) static void qobject_input_free(Visitor *v) { QObjectInputVisitor *qiv =3D to_qiv(v); + while (!QSLIST_EMPTY(&qiv->stack)) { StackObject *tos =3D QSLIST_FIRST(&qiv->stack); =20 @@ -409,6 +459,9 @@ static void qobject_input_free(Visitor *v) } =20 qobject_decref(qiv->root); + if (qiv->errname) { + g_string_free(qiv->errname, TRUE); + } g_free(qiv); } =20 --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887223386288.6952965470276; Thu, 23 Feb 2017 14:00:23 -0800 (PST) Received: from localhost ([::1]:33102 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1R0-0006QB-4h for importer@patchew.org; Thu, 23 Feb 2017 17:00:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34852) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CX-0007lO-DQ for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CU-0004c5-Ni for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38710) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bI-Ic for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AEB967FB7C for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjLKb017621 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:22 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DEC3A1138607; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:09 +0100 Message-Id: <1487886317-27400-14-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 13/21] qapi: Drop string input visitor method optional() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" visit_optional() is to be called only between visit_start_struct() and visit_end_struct(). Visitors that don't support struct visits, i.e. don't implement start_struct(), end_struct(), have no use for it. Clarify documentation. The string input visitor doesn't support struct visits. Its parse_optional() is therefore useless. Drop it. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/visitor-impl.h | 4 ++-- qapi/string-input-visitor.c | 13 ------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 8bd47ee..962ba1d 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -102,8 +102,8 @@ struct Visitor /* Must be set to visit explicit null values. */ void (*type_null)(Visitor *v, const char *name, Error **errp); =20 - /* Must be set for input visitors, optional otherwise. The core - * takes care of the return type in the public interface. */ + /* Must be set for input visitors to visit structs, optional otherwise. + The core takes care of the return type in the public interface. */ void (*optional)(Visitor *v, const char *name, bool *present); =20 /* Must be set */ diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 8dfa561..1a855c5 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -314,18 +314,6 @@ static void parse_type_number(Visitor *v, const char *= name, double *obj, *obj =3D val; } =20 -static void parse_optional(Visitor *v, const char *name, bool *present) -{ - StringInputVisitor *siv =3D to_siv(v); - - if (!siv->string) { - *present =3D false; - return; - } - - *present =3D true; -} - static void string_input_free(Visitor *v) { StringInputVisitor *siv =3D to_siv(v); @@ -351,7 +339,6 @@ Visitor *string_input_visitor_new(const char *str) v->visitor.start_list =3D start_list; v->visitor.next_list =3D next_list; v->visitor.end_list =3D end_list; - v->visitor.optional =3D parse_optional; v->visitor.free =3D string_input_free; =20 v->string =3D str; --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886971761269.7596247826169; Thu, 23 Feb 2017 13:56:11 -0800 (PST) Received: from localhost ([::1]:33081 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Mw-0001gc-9b for importer@patchew.org; Thu, 23 Feb 2017 16:56:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34856) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CX-0007lU-Gb for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CV-0004cE-05 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59864) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CU-0004bM-Kk for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:22 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C881661E73 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6ACFC2D655 for ; Thu, 23 Feb 2017 21:45:22 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E220F113860A; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:10 +0100 Message-Id: <1487886317-27400-15-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 23 Feb 2017 21:45:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 14/21] qapi: Make string input and opts visitor require non-null input X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The string input visitor tries to cope with null input. Null input isn't used anywhere, and isn't covered by tests. Unsurprisingly, it doesn't fully work: start_list() crashes because it passes the input via parse_str() to strtoll() unchecked. Make string_input_visitor_new() assert its argument isn't null, and drop the code trying to deal with null input. The opts visitor crashes when you try to actually visit something with null input. Make opts_visitor_new() assert its argument isn't null, mostly for clarity. qobject_input_visitor_new() already asserts its argument isn't null. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/opts-visitor.c | 1 + qapi/string-input-visitor.c | 54 ++++++++++++++---------------------------= ---- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index a0a7c0e..c50dc4b 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -528,6 +528,7 @@ opts_visitor_new(const QemuOpts *opts) { OptsVisitor *ov; =20 + assert(opts); ov =3D g_malloc0(sizeof *ov); =20 ov->visitor.type =3D VISITOR_INPUT; diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 1a855c5..f126cd9 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -182,12 +182,6 @@ static void parse_type_int64(Visitor *v, const char *n= ame, int64_t *obj, { StringInputVisitor *siv =3D to_siv(v); =20 - if (!siv->string) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "integer"); - return; - } - if (parse_str(siv, name, errp) < 0) { return; } @@ -242,13 +236,7 @@ static void parse_type_size(Visitor *v, const char *na= me, uint64_t *obj, Error *err =3D NULL; uint64_t val; =20 - if (siv->string) { - parse_option_size(name, siv->string, &val, &err); - } else { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "size"); - return; - } + parse_option_size(name, siv->string, &val, &err); if (err) { error_propagate(errp, err); return; @@ -262,19 +250,17 @@ static void parse_type_bool(Visitor *v, const char *n= ame, bool *obj, { StringInputVisitor *siv =3D to_siv(v); =20 - if (siv->string) { - if (!strcasecmp(siv->string, "on") || - !strcasecmp(siv->string, "yes") || - !strcasecmp(siv->string, "true")) { - *obj =3D true; - return; - } - if (!strcasecmp(siv->string, "off") || - !strcasecmp(siv->string, "no") || - !strcasecmp(siv->string, "false")) { - *obj =3D false; - return; - } + if (!strcasecmp(siv->string, "on") || + !strcasecmp(siv->string, "yes") || + !strcasecmp(siv->string, "true")) { + *obj =3D true; + return; + } + if (!strcasecmp(siv->string, "off") || + !strcasecmp(siv->string, "no") || + !strcasecmp(siv->string, "false")) { + *obj =3D false; + return; } =20 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", @@ -285,13 +271,8 @@ static void parse_type_str(Visitor *v, const char *nam= e, char **obj, Error **errp) { StringInputVisitor *siv =3D to_siv(v); - if (siv->string) { - *obj =3D g_strdup(siv->string); - } else { - *obj =3D NULL; - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", - "string"); - } + + *obj =3D g_strdup(siv->string); } =20 static void parse_type_number(Visitor *v, const char *name, double *obj, @@ -302,10 +283,8 @@ static void parse_type_number(Visitor *v, const char *= name, double *obj, double val; =20 errno =3D 0; - if (siv->string) { - val =3D strtod(siv->string, &endp); - } - if (!siv->string || errno || endp =3D=3D siv->string || *endp) { + val =3D strtod(siv->string, &endp); + if (errno || endp =3D=3D siv->string || *endp) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "number"); return; @@ -327,6 +306,7 @@ Visitor *string_input_visitor_new(const char *str) { StringInputVisitor *v; =20 + assert(str); v =3D g_malloc0(sizeof(*v)); =20 v->visitor.type =3D VISITOR_INPUT; --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887499121336.32710572812596; Thu, 23 Feb 2017 14:04:59 -0800 (PST) Received: from localhost ([::1]:33127 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1VN-0002jm-AD for importer@patchew.org; Thu, 23 Feb 2017 17:04:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34875) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CY-0007li-Dh for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004dY-65 for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:14429) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CV-0004cV-Sc for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 022783D945 for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjMN1003317 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:23 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E54BE113860D; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:11 +0100 Message-Id: <1487886317-27400-16-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 15/21] qom: Make object_property_set_qobject()'s input visitor strict X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Commit 240f64b made all qobject input visitors created outside tests strict, except for the one in object_property_set_qobject(). That one was left behind only because Eric couldn't spare the time to figure out whether making it strict would break anything, with a TODO comment. Time to resolve it. Strict makes a difference only for otherwise successful visits of QAPI structs or unions. Let's examine what the callers of object_property_set_qobject() visit: * object_property_set_str(), object_property_set_bool(), object_property_set_int() visit a QString, QBool, QInt, respectively. Strictness can't matter. * qmp_qom_set visits its @value argument. Comes straight from QMP and can be anything ('any' in the QAPI schema). Strictness matters when the property's set() method visits a struct or union QAPI type. No such methods exist, thus switching to strict can't break anything. If we acquire such methods in the future, we'll *want* the visitor to be strict, so that unexpected members get rejected as they should be. Switch to strict. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qom/qom-qobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c index 447e4a0..bbdedda 100644 --- a/qom/qom-qobject.c +++ b/qom/qom-qobject.c @@ -22,8 +22,8 @@ void object_property_set_qobject(Object *obj, QObject *va= lue, const char *name, Error **errp) { Visitor *v; - /* TODO: Should we reject, rather than ignore, excess input? */ - v =3D qobject_input_visitor_new(value, false); + + v =3D qobject_input_visitor_new(value, true); object_property_set(obj, v, name, errp); visit_free(v); } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487886456252817.7032172753779; Thu, 23 Feb 2017 13:47:36 -0800 (PST) Received: from localhost ([::1]:33039 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Ec-0001D8-Pr for importer@patchew.org; Thu, 23 Feb 2017 16:47:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34915) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CZ-0007mD-2l for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004dd-6G for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41266) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CV-0004cX-Sv for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:23 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 02E8CC04B95D for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjMce003318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:23 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E92771138610; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:12 +0100 Message-Id: <1487886317-27400-17-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 16/21] test-qobject-input-visitor: Use strict visitor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The qobject input visitor comes in a strict and a non-strict variant. This test is the non-strict variant's last user. Turns out it relies on non-strict only in test_visitor_in_null(), and just out of laziness. We don't actually test the non-strict behavior. Clean up test_visitor_in_null(), and switch to the strict variant. The next commit will drop the non-strict variant. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- tests/test-qobject-input-visitor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 945404a..125e34c 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -49,7 +49,7 @@ static Visitor *visitor_input_test_init_internal(TestInpu= tVisitorData *data, data->obj =3D qobject_from_jsonv(json_string, ap); g_assert(data->obj); =20 - data->qiv =3D qobject_input_visitor_new(data->obj, false); + data->qiv =3D qobject_input_visitor_new(data->obj, true); g_assert(data->qiv); return data->qiv; } @@ -290,14 +290,14 @@ static void test_visitor_in_null(TestInputVisitorData= *data, * when input is not null. */ =20 - v =3D visitor_input_test_init(data, "{ 'a': null, 'b': '' }"); + v =3D visitor_input_test_init(data, "{ 'a': null, 'b': '', 'c': null }= "); visit_start_struct(v, NULL, NULL, 0, &error_abort); visit_type_null(v, "a", &error_abort); - visit_type_str(v, "a", &tmp, &err); - g_assert(!tmp); - error_free_or_abort(&err); visit_type_null(v, "b", &err); error_free_or_abort(&err); + visit_type_str(v, "c", &tmp, &err); + g_assert(!tmp); + error_free_or_abort(&err); visit_check_struct(v, &error_abort); visit_end_struct(v, NULL); } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887717572275.5626071884743; Thu, 23 Feb 2017 14:08:37 -0800 (PST) Received: from localhost ([::1]:33149 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Yy-0005Zf-A3 for importer@patchew.org; Thu, 23 Feb 2017 17:08:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Ca-0007o8-DX for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004dz-9z for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:28 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59088) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CW-0004cc-1L for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2D97885542 for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjMWC017633 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:23 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id EC8881138613; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:13 +0100 Message-Id: <1487886317-27400-18-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 17/21] qapi: Drop unused non-strict qobject input visitor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The split between tests/test-qobject-input-visitor.c and tests/test-qobject-input-strict.c now makes less sense than ever. The next commit will take care of that. Signed-off-by: Markus Armbruster --- block/nbd.c | 2 +- block/nfs.c | 2 +- block/ssh.c | 2 +- docs/qapi-code-gen.txt | 2 +- include/qapi/qobject-input-visitor.h | 5 +---- qapi/qobject-input-visitor.c | 29 ++++++++++------------------- qmp.c | 2 +- qom/qom-qobject.c | 2 +- scripts/qapi-commands.py | 2 +- target/s390x/cpu_models.c | 2 +- tests/check-qnull.c | 2 +- tests/qmp-test.c | 2 +- tests/test-qmp-commands.c | 2 +- tests/test-qobject-input-strict.c | 2 +- tests/test-qobject-input-visitor.c | 2 +- tests/test-visitor-serialization.c | 2 +- 16 files changed, 25 insertions(+), 37 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index a7f9108..f478f80 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -278,7 +278,7 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict= *options, Error **errp) goto done; } =20 - iv =3D qobject_input_visitor_new(crumpled_addr, true); + iv =3D qobject_input_visitor_new(crumpled_addr); visit_type_SocketAddress(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/block/nfs.c b/block/nfs.c index 0cf115e..2884ad1 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -455,7 +455,7 @@ static NFSServer *nfs_config(QDict *options, Error **er= rp) goto out; } =20 - iv =3D qobject_input_visitor_new(crumpled_addr, true); + iv =3D qobject_input_visitor_new(crumpled_addr); visit_type_NFSServer(iv, NULL, &server, &local_error); if (local_error) { error_propagate(errp, local_error); diff --git a/block/ssh.c b/block/ssh.c index 835932e..278e66f 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -601,7 +601,7 @@ static InetSocketAddress *ssh_config(QDict *options, Er= ror **errp) goto out; } =20 - iv =3D qobject_input_visitor_new(crumpled_addr, true); + iv =3D qobject_input_visitor_new(crumpled_addr); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { error_propagate(errp, local_error); diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 7eb7be1..6746c10 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -1138,7 +1138,7 @@ Example: Visitor *v; UserDefOneList *arg1 =3D NULL; =20 - v =3D qobject_input_visitor_new(QOBJECT(args), true); + v =3D qobject_input_visitor_new(QOBJECT(args)); visit_start_struct(v, NULL, NULL, 0, &err); if (err) { goto out; diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-in= put-visitor.h index cde328d..21db9c4 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -21,10 +21,7 @@ typedef struct QObjectInputVisitor QObjectInputVisitor; =20 /* * Return a new input visitor that converts a QObject to a QAPI object. - * - * Set @strict to reject a parse that doesn't consume all keys of a - * dictionary; otherwise excess input is ignored. */ -Visitor *qobject_input_visitor_new(QObject *obj, bool strict); +Visitor *qobject_input_visitor_new(QObject *obj); =20 #endif diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 8015a98..97a27e2 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -43,9 +43,6 @@ struct QObjectInputVisitor { * QDict or QList). */ QSLIST_HEAD(, StackObject) stack; =20 - /* True to reject parse in visit_end_struct() if unvisited keys remain= . */ - bool strict; - GString *errname; /* Accumulator for full_name() */ }; =20 @@ -157,11 +154,12 @@ static const QListEntry *qobject_input_push(QObjectIn= putVisitor *qiv, tos->obj =3D obj; tos->qapi =3D qapi; =20 - if (qiv->strict && qobject_type(obj) =3D=3D QTYPE_QDICT) { + if (qobject_type(obj) =3D=3D QTYPE_QDICT) { h =3D g_hash_table_new(g_str_hash, g_str_equal); qdict_iter(qobject_to_qdict(obj), qdict_add_key, h); tos->h =3D h; - } else if (qobject_type(obj) =3D=3D QTYPE_QLIST) { + } else { + assert(qobject_type(obj) =3D=3D QTYPE_QLIST); tos->entry =3D qlist_first(qobject_to_qlist(obj)); tos->index =3D -1; } @@ -175,20 +173,15 @@ static void qobject_input_check_struct(Visitor *v, Er= ror **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + GHashTableIter iter; + const char *key; =20 assert(tos && !tos->entry); - if (qiv->strict) { - GHashTable *const top_ht =3D tos->h; - if (top_ht) { - GHashTableIter iter; - const char *key; =20 - g_hash_table_iter_init(&iter, top_ht); - if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { - error_setg(errp, "Parameter '%s' is unexpected", - full_name(qiv, key)); - } - } + g_hash_table_iter_init(&iter, tos->h); + if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { + error_setg(errp, "Parameter '%s' is unexpected", + full_name(qiv, key)); } } =20 @@ -276,7 +269,6 @@ static GenericList *qobject_input_next_list(Visitor *v,= GenericList *tail, return tail->next; } =20 - static void qobject_input_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t s= ize, bool promote_int, Error **errp) @@ -465,7 +457,7 @@ static void qobject_input_free(Visitor *v) g_free(qiv); } =20 -Visitor *qobject_input_visitor_new(QObject *obj, bool strict) +Visitor *qobject_input_visitor_new(QObject *obj) { QObjectInputVisitor *v; =20 @@ -489,7 +481,6 @@ Visitor *qobject_input_visitor_new(QObject *obj, bool s= trict) v->visitor.type_null =3D qobject_input_type_null; v->visitor.optional =3D qobject_input_optional; v->visitor.free =3D qobject_input_free; - v->strict =3D strict; =20 v->root =3D obj; qobject_incref(obj); diff --git a/qmp.c b/qmp.c index dfaabac..fa82b59 100644 --- a/qmp.c +++ b/qmp.c @@ -675,7 +675,7 @@ void qmp_object_add(const char *type, const char *id, pdict =3D qdict_new(); } =20 - v =3D qobject_input_visitor_new(QOBJECT(pdict), true); + v =3D qobject_input_visitor_new(QOBJECT(pdict)); obj =3D user_creatable_add_type(type, id, pdict, v, errp); visit_free(v); if (obj) { diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c index bbdedda..4aec20d 100644 --- a/qom/qom-qobject.c +++ b/qom/qom-qobject.c @@ -23,7 +23,7 @@ void object_property_set_qobject(Object *obj, QObject *va= lue, { Visitor *v; =20 - v =3D qobject_input_visitor_new(value, true); + v =3D qobject_input_visitor_new(value); object_property_set(obj, v, name, errp); visit_free(v); } diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index a75946f..befac8f 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -130,7 +130,7 @@ def gen_marshal(name, arg_type, boxed, ret_type): push_indent() =20 ret +=3D mcgen(''' - v =3D qobject_input_visitor_new(QOBJECT(args), true); + v =3D qobject_input_visitor_new(QOBJECT(args)); visit_start_struct(v, NULL, NULL, 0, &err); if (err) { goto out; diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 5b66d33..784d7b5 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -346,7 +346,7 @@ static void cpu_model_from_info(S390CPUModel *model, co= nst CpuModelInfo *info, } =20 if (qdict) { - visitor =3D qobject_input_visitor_new(info->props, true); + visitor =3D qobject_input_visitor_new(info->props); visit_start_struct(visitor, NULL, NULL, 0, errp); if (*errp) { object_unref(obj); diff --git a/tests/check-qnull.c b/tests/check-qnull.c index b50bb8a..8dd1c96 100644 --- a/tests/check-qnull.c +++ b/tests/check-qnull.c @@ -47,7 +47,7 @@ static void qnull_visit_test(void) =20 g_assert(qnull_.refcnt =3D=3D 1); obj =3D qnull(); - v =3D qobject_input_visitor_new(obj, true); + v =3D qobject_input_visitor_new(obj); qobject_decref(obj); visit_type_null(v, NULL, &error_abort); visit_free(v); diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 405e49e..5d0260b 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -34,7 +34,7 @@ static void test_version(QObject *version) VersionInfo *vinfo; =20 g_assert(version); - v =3D qobject_input_visitor_new(version, true); + v =3D qobject_input_visitor_new(version); visit_type_VersionInfo(v, "version", &vinfo, &error_abort); qapi_free_VersionInfo(vinfo); visit_free(v); diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index c4e20d1..a815056 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -244,7 +244,7 @@ static void test_dealloc_partial(void) ud2_dict =3D qdict_new(); qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text))= ); =20 - v =3D qobject_input_visitor_new(QOBJECT(ud2_dict), true); + v =3D qobject_input_visitor_new(QOBJECT(ud2_dict)); visit_type_UserDefTwo(v, NULL, &ud2, &err); visit_free(v); QDECREF(ud2_dict); diff --git a/tests/test-qobject-input-strict.c b/tests/test-qobject-input-s= trict.c index 4087ea3..7d26113 100644 --- a/tests/test-qobject-input-strict.c +++ b/tests/test-qobject-input-strict.c @@ -53,7 +53,7 @@ static Visitor *validate_test_init_internal(TestInputVisi= torData *data, data->obj =3D qobject_from_jsonv(json_string, ap); g_assert(data->obj); =20 - data->qiv =3D qobject_input_visitor_new(data->obj, true); + data->qiv =3D qobject_input_visitor_new(data->obj); g_assert(data->qiv); return data->qiv; } diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 125e34c..658fa2c 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -49,7 +49,7 @@ static Visitor *visitor_input_test_init_internal(TestInpu= tVisitorData *data, data->obj =3D qobject_from_jsonv(json_string, ap); g_assert(data->obj); =20 - data->qiv =3D qobject_input_visitor_new(data->obj, true); + data->qiv =3D qobject_input_visitor_new(data->obj); g_assert(data->qiv); return data->qiv; } diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serial= ization.c index 66b2b1c..c7e64f0 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -1040,7 +1040,7 @@ static void qmp_deserialize(void **native_out, void *= datap, obj =3D qobject_from_json(qstring_get_str(output_json)); =20 QDECREF(output_json); - d->qiv =3D qobject_input_visitor_new(obj, true); + d->qiv =3D qobject_input_visitor_new(obj); qobject_decref(obj_orig); qobject_decref(obj); visit(d->qiv, native_out, errp); --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887715051686.4925473701943; Thu, 23 Feb 2017 14:08:35 -0800 (PST) Received: from localhost ([::1]:33148 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Yv-0005WQ-2O for importer@patchew.org; Thu, 23 Feb 2017 17:08:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35001) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Cb-0007pU-JY for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004eI-Kt for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:29 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39942) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CW-0004cs-AD for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5A56E4E4CA for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjMcu017635 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:23 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F00411138616; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:14 +0100 Message-Id: <1487886317-27400-19-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 18/21] tests-qobject-input-strict: Merge into test-qobject-input-visitor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Much test-qobject-input-strict.c duplicates test-qobject-input-strict.c less assertions on expected output: * test_validate_struct() duplicates test_visitor_in_struct() * test_validate_struct_nested() duplicates test_visitor_in_struct_nested() * test_validate_list() duplicates the first half of test_visitor_in_list() * test_validate_union_native_list() duplicates test_visitor_in_native_list_int() * test_validate_union_flat() duplicates test_visitor_in_union_flat() * test_validate_alternate() duplicates the first part of test_visitor_in_alternate() Merge the remaining test cases into test-qobject-input-visitor.c, and drop the now redundant test-qobject-input-strict.c. Test case "/visitor/input-strict/fail/list" isn't really about lists, it's about a bad struct nested in a list. Rename accordingly. Signed-off-by: Markus Armbruster --- tests/Makefile.include | 4 +- tests/test-qobject-input-strict.c | 381 ---------------------------------= ---- tests/test-qobject-input-visitor.c | 187 ++++++++++++++++++ 3 files changed, 188 insertions(+), 384 deletions(-) delete mode 100644 tests/test-qobject-input-strict.c diff --git a/tests/Makefile.include b/tests/Makefile.include index b212150..cb97473 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -28,7 +28,6 @@ check-unit-y +=3D tests/test-clone-visitor$(EXESUF) gcov-files-test-clone-visitor-y =3D qapi/qapi-clone-visitor.c check-unit-y +=3D tests/test-qobject-input-visitor$(EXESUF) gcov-files-test-qobject-input-visitor-y =3D qapi/qobject-input-visitor.c -check-unit-y +=3D tests/test-qobject-input-strict$(EXESUF) check-unit-y +=3D tests/test-qmp-commands$(EXESUF) gcov-files-test-qmp-commands-y =3D qapi/qmp-dispatch.c check-unit-y +=3D tests/test-string-input-visitor$(EXESUF) @@ -490,7 +489,7 @@ test-obj-y =3D tests/check-qint.o tests/check-qstring.o= tests/check-qdict.o \ tests/test-coroutine.o tests/test-string-output-visitor.o \ tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \ tests/test-clone-visitor.o \ - tests/test-qobject-input-visitor.o tests/test-qobject-input-strict.o \ + tests/test-qobject-input-visitor.o \ tests/test-qmp-commands.o tests/test-visitor-serialization.o \ tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \ tests/test-opts-visitor.o tests/test-qmp-event.o \ @@ -599,7 +598,6 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $= (test-qapi-obj-y) tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visi= tor.o $(test-qapi-obj-y) tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-= obj-y) tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visito= r.o $(test-qapi-obj-y) -tests/test-qobject-input-strict$(EXESUF): tests/test-qobject-input-strict.= o $(test-qapi-obj-y) tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp= -marshal.o $(test-qapi-obj-y) tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serializatio= n.o $(test-qapi-obj-y) tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-ob= j-y) diff --git a/tests/test-qobject-input-strict.c b/tests/test-qobject-input-s= trict.c deleted file mode 100644 index 7d26113..0000000 --- a/tests/test-qobject-input-strict.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * QObject Input Visitor unit-tests (strict mode). - * - * Copyright (C) 2011-2012, 2015 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * Paolo Bonzini - * - * This work is licensed under the terms of the GNU GPL, version 2 or late= r. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" - -#include "qemu-common.h" -#include "qapi/error.h" -#include "qapi/qobject-input-visitor.h" -#include "test-qapi-types.h" -#include "test-qapi-visit.h" -#include "qapi/qmp/types.h" -#include "qapi/qmp/qjson.h" -#include "test-qmp-introspect.h" -#include "qmp-introspect.h" -#include "qapi-visit.h" - -typedef struct TestInputVisitorData { - QObject *obj; - Visitor *qiv; -} TestInputVisitorData; - -static void validate_teardown(TestInputVisitorData *data, - const void *unused) -{ - qobject_decref(data->obj); - data->obj =3D NULL; - - if (data->qiv) { - visit_free(data->qiv); - data->qiv =3D NULL; - } -} - -/* The various test_init functions are provided instead of a test setup - function so that the JSON string used by the tests are kept in the test - functions (and not in main()). */ -static Visitor *validate_test_init_internal(TestInputVisitorData *data, - const char *json_string, - va_list *ap) -{ - validate_teardown(data, NULL); - - data->obj =3D qobject_from_jsonv(json_string, ap); - g_assert(data->obj); - - data->qiv =3D qobject_input_visitor_new(data->obj); - g_assert(data->qiv); - return data->qiv; -} - -static GCC_FMT_ATTR(2, 3) -Visitor *validate_test_init(TestInputVisitorData *data, - const char *json_string, ...) -{ - Visitor *v; - va_list ap; - - va_start(ap, json_string); - v =3D validate_test_init_internal(data, json_string, &ap); - va_end(ap); - return v; -} - -/* similar to validate_test_init(), but does not expect a string - * literal/format json_string argument and so can be used for - * programatically generated strings (and we can't pass in programatically - * generated strings via %s format parameters since qobject_from_jsonv() - * will wrap those in double-quotes and treat the entire object as a - * string) - */ -static Visitor *validate_test_init_raw(TestInputVisitorData *data, - const char *json_string) -{ - return validate_test_init_internal(data, json_string, NULL); -} - - -static void test_validate_struct(TestInputVisitorData *data, - const void *unused) -{ - TestStruct *p =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'st= ring': 'foo' }"); - - visit_type_TestStruct(v, NULL, &p, &error_abort); - g_free(p->string); - g_free(p); -} - -static void test_validate_struct_nested(TestInputVisitorData *data, - const void *unused) -{ - UserDefTwo *udp =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'string0': 'string0', " - "'dict1': { 'string1': 'string1', " - "'dict2': { 'userdef': { 'integer': 42, " - "'string': 'string' }, 'string': 'string2'}}}"); - - visit_type_UserDefTwo(v, NULL, &udp, &error_abort); - qapi_free_UserDefTwo(udp); -} - -static void test_validate_list(TestInputVisitorData *data, - const void *unused) -{ - UserDefOneList *head =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "[ { 'string': 'string0', 'integer': 42= }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer= ': 44 } ]"); - - visit_type_UserDefOneList(v, NULL, &head, &error_abort); - qapi_free_UserDefOneList(head); -} - -static void test_validate_union_native_list(TestInputVisitorData *data, - const void *unused) -{ - UserDefNativeListUnion *tmp =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ]= }"); - - visit_type_UserDefNativeListUnion(v, NULL, &tmp, &error_abort); - qapi_free_UserDefNativeListUnion(tmp); -} - -static void test_validate_union_flat(TestInputVisitorData *data, - const void *unused) -{ - UserDefFlatUnion *tmp =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, - "{ 'enum1': 'value1', " - "'integer': 41, " - "'string': 'str', " - "'boolean': true }"); - - visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort); - qapi_free_UserDefFlatUnion(tmp); -} - -static void test_validate_alternate(TestInputVisitorData *data, - const void *unused) -{ - UserDefAlternate *tmp =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "42"); - - visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort); - qapi_free_UserDefAlternate(tmp); -} - -static void test_validate_fail_struct(TestInputVisitorData *data, - const void *unused) -{ - TestStruct *p =3D NULL; - Error *err =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'st= ring': 'foo', 'extra': 42 }"); - - visit_type_TestStruct(v, NULL, &p, &err); - error_free_or_abort(&err); - g_assert(!p); -} - -static void test_validate_fail_struct_nested(TestInputVisitorData *data, - const void *unused) -{ - UserDefTwo *udp =3D NULL; - Error *err =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'st= ring1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'strin= g', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}"); - - visit_type_UserDefTwo(v, NULL, &udp, &err); - error_free_or_abort(&err); - g_assert(!udp); -} - -static void test_validate_fail_struct_missing(TestInputVisitorData *data, - const void *unused) -{ - Error *err =3D NULL; - Visitor *v; - QObject *any; - GenericAlternate *alt; - bool present; - int en; - int64_t i64; - uint32_t u32; - int8_t i8; - char *str; - double dbl; - - v =3D validate_test_init(data, "{}"); - visit_start_struct(v, NULL, NULL, 0, &error_abort); - visit_start_struct(v, "struct", NULL, 0, &err); - error_free_or_abort(&err); - visit_start_list(v, "list", NULL, 0, &err); - error_free_or_abort(&err); - visit_start_alternate(v, "alternate", &alt, sizeof(*alt), false, &err); - error_free_or_abort(&err); - visit_optional(v, "optional", &present); - g_assert(!present); - visit_type_enum(v, "enum", &en, EnumOne_lookup, &err); - error_free_or_abort(&err); - visit_type_int(v, "i64", &i64, &err); - error_free_or_abort(&err); - visit_type_uint32(v, "u32", &u32, &err); - error_free_or_abort(&err); - visit_type_int8(v, "i8", &i8, &err); - error_free_or_abort(&err); - visit_type_str(v, "i8", &str, &err); - error_free_or_abort(&err); - visit_type_number(v, "dbl", &dbl, &err); - error_free_or_abort(&err); - visit_type_any(v, "any", &any, &err); - error_free_or_abort(&err); - visit_type_null(v, "null", &err); - error_free_or_abort(&err); - visit_end_struct(v, NULL); -} - -static void test_validate_fail_list(TestInputVisitorData *data, - const void *unused) -{ - UserDefOneList *head =3D NULL; - Error *err =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "[ { 'string': 'string0', 'integer': 42= }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer= ': 44, 'extra': 'ggg' } ]"); - - visit_type_UserDefOneList(v, NULL, &head, &err); - error_free_or_abort(&err); - g_assert(!head); -} - -static void test_validate_fail_union_native_list(TestInputVisitorData *dat= a, - const void *unused) -{ - UserDefNativeListUnion *tmp =3D NULL; - Error *err =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, - "{ 'type': 'integer', 'data' : [ 'string' ] }"); - - visit_type_UserDefNativeListUnion(v, NULL, &tmp, &err); - error_free_or_abort(&err); - g_assert(!tmp); -} - -static void test_validate_fail_union_flat(TestInputVisitorData *data, - const void *unused) -{ - UserDefFlatUnion *tmp =3D NULL; - Error *err =3D NULL; - Visitor *v; - - v =3D validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boole= an': true }"); - - visit_type_UserDefFlatUnion(v, NULL, &tmp, &err); - error_free_or_abort(&err); - g_assert(!tmp); -} - -static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData = *data, - const void *unused) -{ - UserDefFlatUnion2 *tmp =3D NULL; - Error *err =3D NULL; - Visitor *v; - - /* test situation where discriminator field ('enum1' here) is missing = */ - v =3D validate_test_init(data, "{ 'integer': 42, 'string': 'c', 'strin= g1': 'd', 'string2': 'e' }"); - - visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err); - error_free_or_abort(&err); - g_assert(!tmp); -} - -static void test_validate_fail_alternate(TestInputVisitorData *data, - const void *unused) -{ - UserDefAlternate *tmp; - Visitor *v; - Error *err =3D NULL; - - v =3D validate_test_init(data, "3.14"); - - visit_type_UserDefAlternate(v, NULL, &tmp, &err); - error_free_or_abort(&err); - g_assert(!tmp); -} - -static void do_test_validate_qmp_introspect(TestInputVisitorData *data, - const char *schema_json) -{ - SchemaInfoList *schema =3D NULL; - Visitor *v; - - v =3D validate_test_init_raw(data, schema_json); - - visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); - g_assert(schema); - - qapi_free_SchemaInfoList(schema); -} - -static void test_validate_qmp_introspect(TestInputVisitorData *data, - const void *unused) -{ - do_test_validate_qmp_introspect(data, test_qmp_schema_json); - do_test_validate_qmp_introspect(data, qmp_schema_json); -} - -static void validate_test_add(const char *testpath, - TestInputVisitorData *data, - void (*test_func)(TestInputVisitorData *dat= a, const void *user_data)) -{ - g_test_add(testpath, TestInputVisitorData, data, NULL, test_func, - validate_teardown); -} - -int main(int argc, char **argv) -{ - TestInputVisitorData testdata; - - g_test_init(&argc, &argv, NULL); - - validate_test_add("/visitor/input-strict/pass/struct", - &testdata, test_validate_struct); - validate_test_add("/visitor/input-strict/pass/struct-nested", - &testdata, test_validate_struct_nested); - validate_test_add("/visitor/input-strict/pass/list", - &testdata, test_validate_list); - validate_test_add("/visitor/input-strict/pass/union-flat", - &testdata, test_validate_union_flat); - validate_test_add("/visitor/input-strict/pass/alternate", - &testdata, test_validate_alternate); - validate_test_add("/visitor/input-strict/pass/union-native-list", - &testdata, test_validate_union_native_list); - validate_test_add("/visitor/input-strict/fail/struct", - &testdata, test_validate_fail_struct); - validate_test_add("/visitor/input-strict/fail/struct-nested", - &testdata, test_validate_fail_struct_nested); - validate_test_add("/visitor/input-strict/fail/struct-missing", - &testdata, test_validate_fail_struct_missing); - validate_test_add("/visitor/input-strict/fail/list", - &testdata, test_validate_fail_list); - validate_test_add("/visitor/input-strict/fail/union-flat", - &testdata, test_validate_fail_union_flat); - validate_test_add("/visitor/input-strict/fail/union-flat-no-discrimina= tor", - &testdata, test_validate_fail_union_flat_no_discrim); - validate_test_add("/visitor/input-strict/fail/alternate", - &testdata, test_validate_fail_alternate); - validate_test_add("/visitor/input-strict/fail/union-native-list", - &testdata, test_validate_fail_union_native_list); - validate_test_add("/visitor/input-strict/pass/qmp-introspect", - &testdata, test_validate_qmp_introspect); - - g_test_run(); - - return 0; -} diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 658fa2c..32c6b3d 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -5,6 +5,7 @@ * * Authors: * Luiz Capitulino + * Paolo Bonzini * * This work is licensed under the terms of the GNU GPL, version 2 or late= r. * See the COPYING file in the top-level directory. @@ -19,6 +20,9 @@ #include "test-qapi-visit.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qjson.h" +#include "test-qmp-introspect.h" +#include "qmp-introspect.h" +#include "qapi-visit.h" =20 typedef struct TestInputVisitorData { QObject *obj; @@ -833,6 +837,171 @@ static void test_visitor_in_wrong_type(TestInputVisit= orData *data, error_free_or_abort(&err); } =20 +static void test_visitor_in_fail_struct(TestInputVisitorData *data, + const void *unused) +{ + TestStruct *p =3D NULL; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true= , 'string': 'foo', 'extra': 42 }"); + + visit_type_TestStruct(v, NULL, &p, &err); + error_free_or_abort(&err); + g_assert(!p); +} + +static void test_visitor_in_fail_struct_nested(TestInputVisitorData *data, + const void *unused) +{ + UserDefTwo *udp =3D NULL; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': = { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': '= string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}"); + + visit_type_UserDefTwo(v, NULL, &udp, &err); + error_free_or_abort(&err); + g_assert(!udp); +} + +static void test_visitor_in_fail_struct_in_list(TestInputVisitorData *data, + const void *unused) +{ + UserDefOneList *head =3D NULL; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init(data, "[ { 'string': 'string0', 'integer= ': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'in= teger': 44, 'extra': 'ggg' } ]"); + + visit_type_UserDefOneList(v, NULL, &head, &err); + error_free_or_abort(&err); + g_assert(!head); +} + +static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data, + const void *unused) +{ + Error *err =3D NULL; + Visitor *v; + QObject *any; + GenericAlternate *alt; + bool present; + int en; + int64_t i64; + uint32_t u32; + int8_t i8; + char *str; + double dbl; + + v =3D visitor_input_test_init(data, "{}"); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_struct(v, "struct", NULL, 0, &err); + error_free_or_abort(&err); + visit_start_list(v, "list", NULL, 0, &err); + error_free_or_abort(&err); + visit_start_alternate(v, "alternate", &alt, sizeof(*alt), false, &err); + error_free_or_abort(&err); + visit_optional(v, "optional", &present); + g_assert(!present); + visit_type_enum(v, "enum", &en, EnumOne_lookup, &err); + error_free_or_abort(&err); + visit_type_int(v, "i64", &i64, &err); + error_free_or_abort(&err); + visit_type_uint32(v, "u32", &u32, &err); + error_free_or_abort(&err); + visit_type_int8(v, "i8", &i8, &err); + error_free_or_abort(&err); + visit_type_str(v, "i8", &str, &err); + error_free_or_abort(&err); + visit_type_number(v, "dbl", &dbl, &err); + error_free_or_abort(&err); + visit_type_any(v, "any", &any, &err); + error_free_or_abort(&err); + visit_type_null(v, "null", &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); +} + +static void test_visitor_in_fail_union_native_list(TestInputVisitorData *d= ata, + const void *unused) +{ + UserDefNativeListUnion *tmp =3D NULL; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init(data, + "{ 'type': 'integer', 'data' : [ 'string' = ] }"); + + visit_type_UserDefNativeListUnion(v, NULL, &tmp, &err); + error_free_or_abort(&err); + g_assert(!tmp); +} + +static void test_visitor_in_fail_union_flat(TestInputVisitorData *data, + const void *unused) +{ + UserDefFlatUnion *tmp =3D NULL; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init(data, "{ 'string': 'c', 'integer': 41, '= boolean': true }"); + + visit_type_UserDefFlatUnion(v, NULL, &tmp, &err); + error_free_or_abort(&err); + g_assert(!tmp); +} + +static void test_visitor_in_fail_union_flat_no_discrim(TestInputVisitorDat= a *data, + const void *unused) +{ + UserDefFlatUnion2 *tmp =3D NULL; + Error *err =3D NULL; + Visitor *v; + + /* test situation where discriminator field ('enum1' here) is missing = */ + v =3D visitor_input_test_init(data, "{ 'integer': 42, 'string': 'c', '= string1': 'd', 'string2': 'e' }"); + + visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err); + error_free_or_abort(&err); + g_assert(!tmp); +} + +static void test_visitor_in_fail_alternate(TestInputVisitorData *data, + const void *unused) +{ + UserDefAlternate *tmp; + Visitor *v; + Error *err =3D NULL; + + v =3D visitor_input_test_init(data, "3.14"); + + visit_type_UserDefAlternate(v, NULL, &tmp, &err); + error_free_or_abort(&err); + g_assert(!tmp); +} + +static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, + const char *schema_json) +{ + SchemaInfoList *schema =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init_raw(data, schema_json); + + visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); + g_assert(schema); + + qapi_free_SchemaInfoList(schema); +} + +static void test_visitor_in_qmp_introspect(TestInputVisitorData *data, + const void *unused) +{ + do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json); + do_test_visitor_in_qmp_introspect(data, qmp_schema_json); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -893,6 +1062,24 @@ int main(int argc, char **argv) NULL, test_visitor_in_native_list_string); input_visitor_test_add("/visitor/input/native_list/number", NULL, test_visitor_in_native_list_number); + input_visitor_test_add("/visitor/input/fail/struct", + NULL, test_visitor_in_fail_struct); + input_visitor_test_add("/visitor/input/fail/struct-nested", + NULL, test_visitor_in_fail_struct_nested); + input_visitor_test_add("/visitor/input/fail/struct-in-list", + NULL, test_visitor_in_fail_struct_in_list); + input_visitor_test_add("/visitor/input/fail/struct-missing", + NULL, test_visitor_in_fail_struct_missing); + input_visitor_test_add("/visitor/input/fail/union-flat", + NULL, test_visitor_in_fail_union_flat); + input_visitor_test_add("/visitor/input/fail/union-flat-no-discriminato= r", + NULL, test_visitor_in_fail_union_flat_no_discri= m); + input_visitor_test_add("/visitor/input/fail/alternate", + NULL, test_visitor_in_fail_alternate); + input_visitor_test_add("/visitor/input/fail/union-native-list", + NULL, test_visitor_in_fail_union_native_list); + input_visitor_test_add("/visitor/input/qmp-introspect", + NULL, test_visitor_in_qmp_introspect); =20 g_test_run(); =20 --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887721472287.8403776295145; Thu, 23 Feb 2017 14:08:41 -0800 (PST) Received: from localhost ([::1]:33150 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Z2-0005cx-3S for importer@patchew.org; Thu, 23 Feb 2017 17:08:40 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34948) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CZ-0007nO-Ok for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004du-8T for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60188) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CW-0004cb-0O for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2FADA7E9ED for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C5D3E2D653 for ; Thu, 23 Feb 2017 21:45:23 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F345E1138619; Thu, 23 Feb 2017 22:45:17 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:15 +0100 Message-Id: <1487886317-27400-20-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 19/21] tests: Cover partial input visit of list X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Demonstrates a design flaw: there is no way to for input visitors to report that a list visit didn't visit the complete input list. The generated list visits always do, but manual visits needn't. Signed-off-by: Markus Armbruster --- tests/test-opts-visitor.c | 41 ++++++++++++++++++++++++++++++++++= ++++ tests/test-qobject-input-visitor.c | 19 ++++++++++++++++++ tests/test-string-input-visitor.c | 19 ++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c index 0a9e75f..58d0eb1 100644 --- a/tests/test-opts-visitor.c +++ b/tests/test-opts-visitor.c @@ -172,6 +172,44 @@ expect_u64_max(OptsVisitorFixture *f, gconstpointer te= st_data) =20 /* test cases */ =20 +static void +test_opts_range_unvisited(void) +{ + intList *list =3D NULL; + intList *tail; + QemuOpts *opts; + Visitor *v; + + opts =3D qemu_opts_parse(qemu_find_opts("userdef"), "ilist=3D0-2", fal= se, + &error_abort); + + v =3D opts_visitor_new(opts); + + visit_start_struct(v, NULL, NULL, 0, &error_abort); + + /* Would be simpler if opts visitor supported virtual list walks */ + visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list), + &error_abort); + tail =3D list; + visit_type_int(v, NULL, &tail->value, &error_abort); + g_assert_cmpint(tail->value, =3D=3D, 0); + tail =3D (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*li= st)); + g_assert(tail); + visit_type_int(v, NULL, &tail->value, &error_abort); + g_assert_cmpint(tail->value, =3D=3D, 1); + tail =3D (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*li= st)); + g_assert(tail); + visit_end_list(v, (void **)&list); + /* BUG: unvisited tail not reported; actually not reportable by design= */ + + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + + qapi_free_intList(list); + visit_free(v); + qemu_opts_del(opts); +} + int main(int argc, char **argv) { @@ -263,6 +301,9 @@ main(int argc, char **argv) add_test("/visitor/opts/i64/range/2big/full", &expect_fail, "i64=3D-0x8000000000000000-0x7fffffffffffffff"); =20 + g_test_add_func("/visitor/opts/range/unvisited", + test_opts_range_unvisited); + g_test_run(); return 0; } diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 32c6b3d..ac87e75 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -923,6 +923,23 @@ static void test_visitor_in_fail_struct_missing(TestIn= putVisitorData *data, visit_end_struct(v, NULL); } =20 +static void test_visitor_in_fail_list(TestInputVisitorData *data, + const void *unused) +{ + int64_t i64 =3D -1; + Visitor *v; + + v =3D visitor_input_test_init(data, "[ 1, 2, 3 ]"); + + visit_start_list(v, NULL, NULL, 0, &error_abort); + visit_type_int(v, NULL, &i64, &error_abort); + g_assert_cmpint(i64, =3D=3D, 1); + visit_type_int(v, NULL, &i64, &error_abort); + g_assert_cmpint(i64, =3D=3D, 2); + visit_end_list(v, NULL); + /* BUG: unvisited tail not reported; actually not reportable by design= */ +} + static void test_visitor_in_fail_union_native_list(TestInputVisitorData *d= ata, const void *unused) { @@ -1070,6 +1087,8 @@ int main(int argc, char **argv) NULL, test_visitor_in_fail_struct_in_list); input_visitor_test_add("/visitor/input/fail/struct-missing", NULL, test_visitor_in_fail_struct_missing); + input_visitor_test_add("/visitor/input/fail/list", + NULL, test_visitor_in_fail_list); input_visitor_test_add("/visitor/input/fail/union-flat", NULL, test_visitor_in_fail_union_flat); input_visitor_test_add("/visitor/input/fail/union-flat-no-discriminato= r", diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-vi= sitor.c index 7f10e25..bb50473 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -94,6 +94,25 @@ static void test_visitor_in_intList(TestInputVisitorData= *data, visit_type_int16List(v, NULL, &res, &err); error_free_or_abort(&err); g_assert(!res); + + v =3D visitor_input_test_init(data, "0,2-3"); + + /* Would be simpler if opts visitor supported virtual list walks */ + visit_start_list(v, NULL, (GenericList **)&res, sizeof(*res), + &error_abort); + tmp =3D res; + visit_type_int16(v, NULL, &tmp->value, &error_abort); + g_assert_cmpint(tmp->value, =3D=3D, 0); + tmp =3D (int16List *)visit_next_list(v, (GenericList *)tmp, sizeof(*re= s)); + g_assert(tmp); + visit_type_int16(v, NULL, &tmp->value, &error_abort); + g_assert_cmpint(tmp->value, =3D=3D, 2); + tmp =3D (int16List *)visit_next_list(v, (GenericList *)tmp, sizeof(*re= s)); + g_assert(tmp); + visit_end_list(v, (void **)&res); + /* BUG: unvisited tail not reported; actually not reportable by design= */ + + qapi_free_int16List(res); } =20 static void test_visitor_in_bool(TestInputVisitorData *data, --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887922195867.10414621248; Thu, 23 Feb 2017 14:12:02 -0800 (PST) Received: from localhost ([::1]:33187 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1cF-00012q-P1 for importer@patchew.org; Thu, 23 Feb 2017 17:11:59 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34974) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1Ca-0007oI-Gx for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004eD-Ii for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:28 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49250) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CW-0004ct-8i for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5CAE383F38 for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C61392D654 for ; Thu, 23 Feb 2017 21:45:23 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 0267D113861C; Thu, 23 Feb 2017 22:45:18 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:16 +0100 Message-Id: <1487886317-27400-21-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 20/21] qapi: Make input visitors detect unvisited list tails X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Fix the design flaw demonstrated in the previous commit: new method check_list() lets input visitors report that unvisited input remains for a list, exactly like check_struct() lets them report that unvisited input remains for a struct or union. Implement the method for the qobject input visitor (straightforward), and the string input visitor (less so, due to the magic list syntax there). The opts visitor's list magic is even more impenetrable, and all I can do there today is a stub with a FIXME comment. No worse than before. Signed-off-by: Markus Armbruster --- hw/ppc/spapr_drc.c | 5 +++++ include/qapi/visitor-impl.h | 3 +++ include/qapi/visitor.h | 13 +++++++++++++ qapi/opts-visitor.c | 11 +++++++++++ qapi/qapi-visit-core.c | 8 ++++++++ qapi/qobject-input-visitor.c | 35 +++++++++++++++++++++++++++++++---- qapi/string-input-visitor.c | 30 ++++++++++++++++++++++++++++++ qapi/trace-events | 1 + scripts/qapi-visit.py | 3 +++ tests/test-opts-visitor.c | 2 +- tests/test-qobject-input-visitor.c | 4 +++- tests/test-string-input-visitor.c | 3 ++- 12 files changed, 111 insertions(+), 7 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 2de6377..fe7b988 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -326,6 +326,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, cons= t char *name, return; } } + visit_check_list(v, &err); + if (err) { + error_propagate(errp, err); + return; + } visit_end_list(v, NULL); break; } diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 962ba1d..e87709d 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -61,6 +61,9 @@ struct Visitor /* Must be set */ GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size); =20 + /* Optional; intended for input visitors */ + void (*check_list)(Visitor *v, Error **errp); + /* Must be set */ void (*end_list)(Visitor *v, void **list); =20 diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 7c91a50..1a1b620 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -370,6 +370,19 @@ void visit_start_list(Visitor *v, const char *name, Ge= nericList **list, GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); =20 /* + * Prepare for completing a list visit. + * + * @errp obeys typical error usage, and reports failures such as + * unvisited list tail remaining in the input stream. + * + * Should be called prior to visit_end_list() if all other + * intermediate visit steps were successful, to allow the visitor one + * last chance to report errors. May be skipped on a cleanup path, + * where there is no need to check for further errors. + */ +void visit_check_list(Visitor *v, Error **errp); + +/* * Complete a list visit started earlier. * * @list must match what was passed to the paired visit_start_list(). diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index c50dc4b..026d25b 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -273,6 +273,16 @@ opts_next_list(Visitor *v, GenericList *tail, size_t s= ize) =20 =20 static void +opts_check_list(Visitor *v, Error **errp) +{ + /* + * FIXME should set error when unvisited elements remain. Mostly + * harmless, as the generated visits always visit all elements. + */ +} + + +static void opts_end_list(Visitor *v, void **obj) { OptsVisitor *ov =3D to_ov(v); @@ -539,6 +549,7 @@ opts_visitor_new(const QemuOpts *opts) =20 ov->visitor.start_list =3D &opts_start_list; ov->visitor.next_list =3D &opts_next_list; + ov->visitor.check_list =3D &opts_check_list; ov->visitor.end_list =3D &opts_end_list; =20 ov->visitor.type_int64 =3D &opts_type_int64; diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index e6e93f0..43a09d1 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -90,6 +90,14 @@ GenericList *visit_next_list(Visitor *v, GenericList *ta= il, size_t size) return v->next_list(v, tail, size); } =20 +void visit_check_list(Visitor *v, Error **errp) +{ + trace_visit_check_list(v); + if (v->check_list) { + v->check_list(v, errp); + } +} + void visit_end_list(Visitor *v, void **obj) { trace_visit_end_list(v, obj); diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 97a27e2..0229046 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -51,7 +51,8 @@ static QObjectInputVisitor *to_qiv(Visitor *v) return container_of(v, QObjectInputVisitor, visitor); } =20 -static const char *full_name(QObjectInputVisitor *qiv, const char *name) +static const char *full_name_nth(QObjectInputVisitor *qiv, const char *nam= e, + int n) { StackObject *so; char buf[32]; @@ -63,6 +64,10 @@ static const char *full_name(QObjectInputVisitor *qiv, c= onst char *name) } =20 QSLIST_FOREACH(so , &qiv->stack, node) { + if (n > 0) { + n--; + continue; + } if (qobject_type(so->obj) =3D=3D QTYPE_QDICT) { g_string_prepend(qiv->errname, name); g_string_prepend_c(qiv->errname, '.'); @@ -72,18 +77,24 @@ static const char *full_name(QObjectInputVisitor *qiv, = const char *name) } name =3D so->name; } + assert(!n); =20 if (name) { g_string_prepend(qiv->errname, name); } else if (qiv->errname->str[0] =3D=3D '.') { g_string_erase(qiv->errname, 0, 1); - } else { + } else if (!qiv->errname->str[0]) { return ""; } =20 return qiv->errname->str; } =20 +static const char *full_name(QObjectInputVisitor *qiv, const char *name) +{ + return full_name_nth(qiv, name, 0); +} + static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv, const char *name, bool consume) @@ -260,15 +271,30 @@ static GenericList *qobject_input_next_list(Visitor *= v, GenericList *tail, size_t size) { QObjectInputVisitor *qiv =3D to_qiv(v); - StackObject *so =3D QSLIST_FIRST(&qiv->stack); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); =20 - if (!so->entry) { + assert(tos && tos->obj && qobject_type(tos->obj) =3D=3D QTYPE_QLIST); + + if (!tos->entry) { return NULL; } tail->next =3D g_malloc0(size); return tail->next; } =20 +static void qobject_input_check_list(Visitor *v, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + + assert(tos && tos->obj && qobject_type(tos->obj) =3D=3D QTYPE_QLIST); + + if (tos->entry) { + error_setg(errp, "Only %u list elements expected in %s", + tos->index + 1, full_name_nth(qiv, NULL, 1)); + } +} + static void qobject_input_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t s= ize, bool promote_int, Error **errp) @@ -470,6 +496,7 @@ Visitor *qobject_input_visitor_new(QObject *obj) v->visitor.end_struct =3D qobject_input_pop; v->visitor.start_list =3D qobject_input_start_list; v->visitor.next_list =3D qobject_input_next_list; + v->visitor.check_list =3D qobject_input_check_list; v->visitor.end_list =3D qobject_input_pop; v->visitor.start_alternate =3D qobject_input_start_alternate; v->visitor.type_int64 =3D qobject_input_type_int64; diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index f126cd9..806b01ae 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -170,6 +170,35 @@ static GenericList *next_list(Visitor *v, GenericList = *tail, size_t size) return tail->next; } =20 +static void check_list(Visitor *v, Error **errp) +{ + const StringInputVisitor *siv =3D to_siv(v); + Range *r; + GList *cur_range; + + if (!siv->ranges || !siv->cur_range) { + return; + } + + r =3D siv->cur_range->data; + if (!r) { + return; + } + + if (!range_contains(r, siv->cur)) { + cur_range =3D g_list_next(siv->cur_range); + if (!cur_range) { + return; + } + r =3D cur_range->data; + if (!r) { + return; + } + } + + error_setg(errp, "Range contains too many values"); +} + static void end_list(Visitor *v, void **obj) { StringInputVisitor *siv =3D to_siv(v); @@ -318,6 +347,7 @@ Visitor *string_input_visitor_new(const char *str) v->visitor.type_number =3D parse_type_number; v->visitor.start_list =3D start_list; v->visitor.next_list =3D next_list; + v->visitor.check_list =3D check_list; v->visitor.end_list =3D end_list; v->visitor.free =3D string_input_free; =20 diff --git a/qapi/trace-events b/qapi/trace-events index 9cbb61b..339cacf 100644 --- a/qapi/trace-events +++ b/qapi/trace-events @@ -8,6 +8,7 @@ visit_end_struct(void *v, void *obj) "v=3D%p obj=3D%p" =20 visit_start_list(void *v, const char *name, void *obj, size_t size) "v=3D%= p name=3D%s obj=3D%p size=3D%zu" visit_next_list(void *v, void *tail, size_t size) "v=3D%p tail=3D%p size= =3D%zu" +visit_check_list(void *v) "v=3D%p" visit_end_list(void *v, void *obj) "v=3D%p obj=3D%p" =20 visit_start_alternate(void *v, const char *name, void *obj, size_t size, b= ool promote_int) "v=3D%p name=3D%s obj=3D%p size=3D%zu promote_int=3D%d" diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 96f2491..330b9f3 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -133,6 +133,9 @@ void visit_type_%(c_name)s(Visitor *v, const char *name= , %(c_name)s **obj, Error } } =20 + if (!err) { + visit_check_list(v, &err); + } visit_end_list(v, (void **)obj); if (err && visit_is_input(v)) { qapi_free_%(c_name)s(*obj); diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c index 58d0eb1..1efd327 100644 --- a/tests/test-opts-visitor.c +++ b/tests/test-opts-visitor.c @@ -199,8 +199,8 @@ test_opts_range_unvisited(void) g_assert_cmpint(tail->value, =3D=3D, 1); tail =3D (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*li= st)); g_assert(tail); + visit_check_list(v, &error_abort); /* BUG: unvisited tail not reported= */ visit_end_list(v, (void **)&list); - /* BUG: unvisited tail not reported; actually not reportable by design= */ =20 visit_check_struct(v, &error_abort); visit_end_struct(v, NULL); diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index ac87e75..bb5bdf4 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -927,6 +927,7 @@ static void test_visitor_in_fail_list(TestInputVisitorD= ata *data, const void *unused) { int64_t i64 =3D -1; + Error *err =3D NULL; Visitor *v; =20 v =3D visitor_input_test_init(data, "[ 1, 2, 3 ]"); @@ -936,8 +937,9 @@ static void test_visitor_in_fail_list(TestInputVisitorD= ata *data, g_assert_cmpint(i64, =3D=3D, 1); visit_type_int(v, NULL, &i64, &error_abort); g_assert_cmpint(i64, =3D=3D, 2); + visit_check_list(v, &err); + error_free_or_abort(&err); visit_end_list(v, NULL); - /* BUG: unvisited tail not reported; actually not reportable by design= */ } =20 static void test_visitor_in_fail_union_native_list(TestInputVisitorData *d= ata, diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-vi= sitor.c index bb50473..d101cc2 100644 --- a/tests/test-string-input-visitor.c +++ b/tests/test-string-input-visitor.c @@ -109,8 +109,9 @@ static void test_visitor_in_intList(TestInputVisitorDat= a *data, g_assert_cmpint(tmp->value, =3D=3D, 2); tmp =3D (int16List *)visit_next_list(v, (GenericList *)tmp, sizeof(*re= s)); g_assert(tmp); + visit_check_list(v, &err); + error_free_or_abort(&err); visit_end_list(v, (void **)&res); - /* BUG: unvisited tail not reported; actually not reportable by design= */ =20 qapi_free_int16List(res); } --=20 2.7.4 From nobody Sun May 5 04:25:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487887490013288.6085855389873; Thu, 23 Feb 2017 14:04:50 -0800 (PST) Received: from localhost ([::1]:33126 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1VI-0002fm-R7 for importer@patchew.org; Thu, 23 Feb 2017 17:04:48 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34956) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ch1CZ-0007nZ-Rh for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ch1CW-0004e6-FK for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41268) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ch1CW-0004ch-5c for qemu-devel@nongnu.org; Thu, 23 Feb 2017 16:45:24 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3CF29C04BD2E for ; Thu, 23 Feb 2017 21:45:24 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1NLjMTh010516 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 23 Feb 2017 16:45:23 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 05E24113861F; Thu, 23 Feb 2017 22:45:18 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 23 Feb 2017 22:45:17 +0100 Message-Id: <1487886317-27400-22-git-send-email-armbru@redhat.com> In-Reply-To: <1487886317-27400-1-git-send-email-armbru@redhat.com> References: <1487886317-27400-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 23 Feb 2017 21:45:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 21/21] qapi: Improve qobject visitor documentation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster --- include/qapi/qobject-input-visitor.h | 36 +++++++++++++++++++++++++++++++= +++- include/qapi/qobject-output-visitor.h | 35 ++++++++++++++++++++++++++++++-= --- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-in= put-visitor.h index 21db9c4..3ca233a 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -20,7 +20,41 @@ typedef struct QObjectInputVisitor QObjectInputVisitor; =20 /* - * Return a new input visitor that converts a QObject to a QAPI object. + * Create a QObject input visitor for @obj + * + * A QObject input visitor visit builds a QAPI object from a QObject. + * This simultaneously walks the QAPI object being built and the + * QObject. The latter walk starts at @obj. + * + * visit_type_FOO() creates an instance of QAPI type FOO. The visited + * QObject must match FOO. QDict matches struct/union types, QList + * matches list types, QString matches type 'str' and enumeration + * types, QInt matches integer types, QFloat matches type 'number', + * QBool matches type 'bool'. Type 'any' is matched by QObject. A + * QAPI alternate type is matched when one of its member types is. + * + * visit_start_struct() ... visit_end_struct() visits a QDict and + * creates a QAPI struct/union. Visits in between visit the + * dictionary members. visit_optional() is true when the QDict has + * this member. visit_check_struct() fails if unvisited members + * remain. + * + * visit_start_list() ... visit_end_list() visits a QList and creates + * a QAPI list. Visits in between visit list members, one after the + * other. visit_next_list() returns NULL when all QList members have + * been visited. visit_check_list() fails if unvisited members + * remain. + * + * visit_start_alternate() ... visit_end_alternate() visits a QObject + * and creates a QAPI alternate. The visit in between visits the same + * QObject and initializes the alternate member that is in use. + * + * Error messages refer to parts of @obj in JavaScript/Python syntax. + * For example, 'a.b[2]' refers to the second member of the QList + * member 'b' of the QDict member 'a' of QDict @obj. + * + * The caller is responsible for freeing the visitor with + * visit_free(). */ Visitor *qobject_input_visitor_new(QObject *obj); =20 diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-o= utput-visitor.h index 8241877..9b990c3 100644 --- a/include/qapi/qobject-output-visitor.h +++ b/include/qapi/qobject-output-visitor.h @@ -19,11 +19,38 @@ =20 typedef struct QObjectOutputVisitor QObjectOutputVisitor; =20 -/* - * Create a new QObject output visitor. +/** + * Create a QObject output visitor for @obj * - * If everything else succeeds, pass @result to visit_complete() to - * collect the result of the visit. + * A QObject output visitor visit builds a QObject from QAPI Object. + * This simultaneously walks the QAPI object and the QObject being + * built. The latter walk starts at @obj. + * + * visit_type_FOO() creates a QObject for QAPI type FOO. It creates a + * QDict for struct/union types, a QList for list types, QString for + * type 'str' and enumeration types, QInt for integer types, QFloat + * for type 'number', QBool for type 'bool'. For type 'any', it + * increments the QObject's reference count. For QAPI alternate + * types, it creates the QObject for the member that is in use. + * + * visit_start_struct() ... visit_end_struct() visits a QAPI + * struct/union and creates a QDict. Visits in between visit the + * members. visit_optional() is true when the struct/union has this + * member. visit_check_struct() does nothing. + * + * visit_start_list() ... visit_end_list() visits a QAPI list and + * creates a QList. Visits in between visit list members, one after + * the other. visit_next_list() returns NULL when all QAPI list + * members have been visited. visit_check_list() does nothing. + * + * visit_start_alternate() ... visit_end_alternate() visits a QAPI + * alternate. The visit in between creates the QObject for the + * alternate member that is in use. + * + * Errors are not expected to happen. + * + * The caller is responsible for freeing the visitor with + * visit_free(). */ Visitor *qobject_output_visitor_new(QObject **result); =20 --=20 2.7.4