From nobody Sun May 5 07:43:36 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 1488320979054708.1448872359081; Tue, 28 Feb 2017 14:29:39 -0800 (PST) Received: from localhost ([::1]:37392 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqH3-00078u-NW for importer@patchew.org; Tue, 28 Feb 2017 17:29:37 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33603) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056d-VN for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDq-0000WB-Iq for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38622) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDq-0000Ve-DS for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:18 -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 8270280B22 for ; Tue, 28 Feb 2017 22:26:18 +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 v1SMQHBt017503 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:18 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id AD94D113864A; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:52 +0100 Message-Id: <1488320775-9849-2-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26:18 +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] [PULL 01/24] test-qemu-opts: Cover qemu_opts_parse() of "no" 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" qemu_opts_parse() interprets "no" as negated empty key. Consistent with its acceptance of empty keys elsewhere, whatever that's worth. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-2-git-send-email-armbru@redhat.com> --- tests/test-qemu-opts.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index c46ef31..f6310b3 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -532,6 +532,11 @@ static void test_opts_parse(void) g_assert_cmpstr(qemu_opt_get(opts, "aus"), =3D=3D, "off"); g_assert_cmpstr(qemu_opt_get(opts, "noaus"), =3D=3D, ""); =20 + /* Implied value, negated empty key */ + opts =3D qemu_opts_parse(&opts_list_03, "no", false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opt_get(opts, ""), =3D=3D, "off"); + /* Implied key */ opts =3D qemu_opts_parse(&opts_list_03, "an,noaus,noaus=3D", true, &error_abort); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488320882328430.6801369992818; Tue, 28 Feb 2017 14:28:02 -0800 (PST) Received: from localhost ([::1]:37385 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqFU-0005iA-L3 for importer@patchew.org; Tue, 28 Feb 2017 17:28:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33596) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056T-Rv for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDq-0000W5-HM for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:50978) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDq-0000Vd-CF for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:18 -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 7AAB03B71B for ; Tue, 28 Feb 2017 22:26:18 +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 46B241DCC0 for ; Tue, 28 Feb 2017 22:26:18 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B032F113864D; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:53 +0100 Message-Id: <1488320775-9849-3-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.30]); Tue, 28 Feb 2017 22:26:18 +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] [PULL 02/24] tests: Fix gcov-files-test-qemu-opts-y, gcov-files-test-logging-y 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 Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-3-git-send-email-armbru@redhat.com> --- tests/Makefile.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 8b3e2bd..35d07e4 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -93,7 +93,7 @@ gcov-files-check-qom-interface-y =3D qom/object.c check-unit-y +=3D tests/check-qom-proplist$(EXESUF) gcov-files-check-qom-proplist-y =3D qom/object.c check-unit-y +=3D tests/test-qemu-opts$(EXESUF) -gcov-files-test-qemu-opts-y =3D qom/test-qemu-opts.c +gcov-files-test-qemu-opts-y =3D util/qemu-option.c check-unit-y +=3D tests/test-write-threshold$(EXESUF) gcov-files-test-write-threshold-y =3D block/write-threshold.c check-unit-y +=3D tests/test-crypto-hash$(EXESUF) @@ -118,8 +118,8 @@ check-unit-y +=3D tests/test-crypto-ivgen$(EXESUF) check-unit-y +=3D tests/test-crypto-afsplit$(EXESUF) check-unit-y +=3D tests/test-crypto-xts$(EXESUF) check-unit-y +=3D tests/test-crypto-block$(EXESUF) -gcov-files-test-logging-y =3D tests/test-logging.c check-unit-y +=3D tests/test-logging$(EXESUF) +gcov-files-test-logging-y =3D util/log.c check-unit-$(CONFIG_REPLICATION) +=3D tests/test-replication$(EXESUF) check-unit-y +=3D tests/test-bufferiszero$(EXESUF) gcov-files-check-bufferiszero-y =3D util/bufferiszero.c --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321120377747.727307324238; Tue, 28 Feb 2017 14:32:00 -0800 (PST) Received: from localhost ([::1]:37406 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqJK-0000rR-TC for importer@patchew.org; Tue, 28 Feb 2017 17:31:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33601) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056b-UO for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDq-0000Ww-Uj for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:50980) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDq-0000Vn-Mq for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:18 -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 E07983B71F for ; Tue, 28 Feb 2017 22:26:18 +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 v1SMQHrH017505 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:18 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B39491138650; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:54 +0100 Message-Id: <1488320775-9849-4-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.30]); Tue, 28 Feb 2017 22:26:18 +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] [PULL 03/24] keyval: New keyval_parse() 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" keyval_parse() parses KEY=3DVALUE,... into a QDict. Works like qemu_opts_parse(), except: * Returns a QDict instead of a QemuOpts (d'oh). * Supports nesting, unlike QemuOpts: a KEY is split into key fragments at '.' (dotted key convention; the block layer does something similar on top of QemuOpts). The key fragments are QDict keys, and the last one's value is updated to VALUE. * Each key fragment may be up to 127 bytes long. qemu_opts_parse() limits the entire key to 127 bytes. * Overlong key fragments are rejected. qemu_opts_parse() silently truncates them. * Empty key fragments are rejected. qemu_opts_parse() happily accepts empty keys. * It does not store the returned value. qemu_opts_parse() stores it in the QemuOptsList. * It does not treat parameter "id" specially. qemu_opts_parse() ignores all but the first "id", and fails when its value isn't id_wellformed(), or duplicate (a QemuOpts with the same ID is already stored). It also screws up when a value contains ",id=3D". * Implied value is not supported. qemu_opts_parse() desugars "foo" to "foo=3Don", and "nofoo" to "foo=3Doff". * An implied key's value can't be empty, and can't contain ','. I intend to grow this into a saner replacement for QemuOpts. It'll take time, though. Note: keyval_parse() provides no way to do lists, and its key syntax is incompatible with the __RFQDN_ prefix convention for downstream extensions, because it blindly splits at '.', even in __RFQDN_. Both issues will be addressed later in the series. Signed-off-by: Markus Armbruster Message-Id: <1488317230-26248-4-git-send-email-armbru@redhat.com> --- include/qemu/option.h | 3 + tests/.gitignore | 1 + tests/Makefile.include | 3 + tests/test-keyval.c | 180 ++++++++++++++++++++++++++++++++++++++ util/Makefile.objs | 1 + util/keyval.c | 231 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 6 files changed, 419 insertions(+) create mode 100644 tests/test-keyval.c create mode 100644 util/keyval.c diff --git a/include/qemu/option.h b/include/qemu/option.h index e786df0..f7338db 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -141,4 +141,7 @@ void qemu_opts_print_help(QemuOptsList *list); void qemu_opts_free(QemuOptsList *list); QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); =20 +QDict *keyval_parse(const char *params, const char *implied_key, + Error **errp); + #endif diff --git a/tests/.gitignore b/tests/.gitignore index dc37519..30b7740 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -47,6 +47,7 @@ test-io-channel-file.txt test-io-channel-socket test-io-channel-tls test-io-task +test-keyval test-logging test-mul64 test-opts-visitor diff --git a/tests/Makefile.include b/tests/Makefile.include index 35d07e4..e3b4f27 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -94,6 +94,8 @@ check-unit-y +=3D tests/check-qom-proplist$(EXESUF) gcov-files-check-qom-proplist-y =3D qom/object.c check-unit-y +=3D tests/test-qemu-opts$(EXESUF) gcov-files-test-qemu-opts-y =3D util/qemu-option.c +check-unit-y +=3D tests/test-keyval$(EXESUF) +gcov-files-test-keyval-y =3D util/keyval.c check-unit-y +=3D tests/test-write-threshold$(EXESUF) gcov-files-test-write-threshold-y =3D block/write-threshold.c check-unit-y +=3D tests/test-crypto-hash$(EXESUF) @@ -720,6 +722,7 @@ tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o= $(test-util-obj-y) \ $(chardev-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_s= cm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y) +tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-b= lock-obj-y) tests/test-netfilter$(EXESUF): tests/test-netfilter.o $(qtest-obj-y) tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-= y) diff --git a/tests/test-keyval.c b/tests/test-keyval.c new file mode 100644 index 0000000..27f6625 --- /dev/null +++ b/tests/test-keyval.c @@ -0,0 +1,180 @@ +/* + * Unit tests for parsing of KEY=3DVALUE,... strings + * + * 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 "qapi/error.h" +#include "qemu/option.h" + +static void test_keyval_parse(void) +{ + Error *err =3D NULL; + QDict *qdict, *sub_qdict; + char long_key[129]; + char *params; + + /* Nothing */ + qdict =3D keyval_parse("", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 0); + QDECREF(qdict); + + /* Empty key (qemu_opts_parse() accepts this) */ + qdict =3D keyval_parse("=3Dval", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Empty key fragment */ + qdict =3D keyval_parse(".", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + qdict =3D keyval_parse("key.", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Overlong key */ + memset(long_key, 'a', 127); + long_key[127] =3D 'z'; + long_key[128] =3D 0; + params =3D g_strdup_printf("k.%s=3Dv", long_key); + qdict =3D keyval_parse(params + 2, NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Overlong key fragment */ + qdict =3D keyval_parse(params, NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + g_free(params); + + /* Long key (qemu_opts_parse() accepts and truncates silently) */ + params =3D g_strdup_printf("k.%s=3Dv", long_key + 1); + qdict =3D keyval_parse(params + 2, NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), =3D=3D, "v"); + QDECREF(qdict); + + /* Long key fragment */ + qdict =3D keyval_parse(params, NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + sub_qdict =3D qdict_get_qdict(qdict, "k"); + g_assert(sub_qdict); + g_assert_cmpuint(qdict_size(sub_qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), =3D=3D, "v= "); + QDECREF(qdict); + g_free(params); + + /* Multiple keys, last one wins */ + qdict =3D keyval_parse("a=3D1,b=3D2,,x,a=3D3", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 2); + g_assert_cmpstr(qdict_get_try_str(qdict, "a"), =3D=3D, "3"); + g_assert_cmpstr(qdict_get_try_str(qdict, "b"), =3D=3D, "2,x"); + QDECREF(qdict); + + /* Even when it doesn't in qemu_opts_parse() */ + qdict =3D keyval_parse("id=3Dfoo,id=3Dbar", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "id"), =3D=3D, "bar"); + QDECREF(qdict); + + /* Dotted keys */ + qdict =3D keyval_parse("a.b.c=3D1,a.b.c=3D2,d=3D3", NULL, &error_abort= ); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 2); + sub_qdict =3D qdict_get_qdict(qdict, "a"); + g_assert(sub_qdict); + g_assert_cmpuint(qdict_size(sub_qdict), =3D=3D, 1); + sub_qdict =3D qdict_get_qdict(sub_qdict, "b"); + g_assert(sub_qdict); + g_assert_cmpuint(qdict_size(sub_qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), =3D=3D, "2"); + g_assert_cmpstr(qdict_get_try_str(qdict, "d"), =3D=3D, "3"); + QDECREF(qdict); + + /* Inconsistent dotted keys */ + qdict =3D keyval_parse("a.b=3D1,a=3D2", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + qdict =3D keyval_parse("a.b=3D1,a.b.c=3D2", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Trailing comma is ignored */ + qdict =3D keyval_parse("x=3Dy,", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "x"), =3D=3D, "y"); + QDECREF(qdict); + + /* Except when it isn't */ + qdict =3D keyval_parse(",", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Value containing ,id=3D not misinterpreted as qemu_opts_parse() doe= s */ + qdict =3D keyval_parse("x=3D,,id=3Dbar", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "x"), =3D=3D, ",id=3Dbar"); + QDECREF(qdict); + + /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */ + qdict =3D keyval_parse("id=3D666", NULL, &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(qdict, "id"), =3D=3D, "666"); + QDECREF(qdict); + + /* Implied value not supported (unlike qemu_opts_parse()) */ + qdict =3D keyval_parse("an,noaus,noaus=3D", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */ + qdict =3D keyval_parse("no", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Implied key */ + qdict =3D keyval_parse("an,aus=3Doff,noaus=3D", "implied", &error_abor= t); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 3); + g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), =3D=3D, "an"); + g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), =3D=3D, "off"); + g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), =3D=3D, ""); + QDECREF(qdict); + + /* Implied dotted key */ + qdict =3D keyval_parse("val", "eins.zwei", &error_abort); + g_assert_cmpuint(qdict_size(qdict), =3D=3D, 1); + sub_qdict =3D qdict_get_qdict(qdict, "eins"); + g_assert(sub_qdict); + g_assert_cmpuint(qdict_size(sub_qdict), =3D=3D, 1); + g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), =3D=3D, "val"); + QDECREF(qdict); + + /* Implied key with empty value (qemu_opts_parse() accepts this) */ + qdict =3D keyval_parse(",", "implied", &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Likewise (qemu_opts_parse(): implied key with comma value) */ + qdict =3D keyval_parse(",,,a=3D1", "implied", &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Empty key is not an implied key */ + qdict =3D keyval_parse("=3Dval", "implied", &err); + error_free_or_abort(&err); + g_assert(!qdict); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/keyval/keyval_parse", test_keyval_parse); + g_test_run(); + return 0; +} diff --git a/util/Makefile.objs b/util/Makefile.objs index bc629e2..06366b5 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -24,6 +24,7 @@ util-obj-y +=3D error.o qemu-error.o util-obj-y +=3D id.o util-obj-y +=3D iov.o qemu-config.o qemu-sockets.o uri.o notify.o util-obj-y +=3D qemu-option.o qemu-progress.o +util-obj-y +=3D keyval.o util-obj-y +=3D hexdump.o util-obj-y +=3D crc32c.o util-obj-y +=3D uuid.o diff --git a/util/keyval.c b/util/keyval.c new file mode 100644 index 0000000..990126f --- /dev/null +++ b/util/keyval.c @@ -0,0 +1,231 @@ +/* + * Parsing KEY=3DVALUE,... strings + * + * 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. + */ + +/* + * KEY=3DVALUE,... syntax: + * + * key-vals =3D [ key-val { ',' key-val } [ ',' ] ] + * key-val =3D key '=3D' val + * key =3D key-fragment { '.' key-fragment } + * key-fragment =3D / [^=3D,.]* / + * val =3D { / [^,]* / | ',,' } + * + * Semantics defined by reduction to JSON: + * + * key-vals defines a tree of objects rooted at R + * where for each key-val =3D key-fragment . ... =3D val in key-vals + * R op key-fragment op ... =3D val' + * where (left-associative) op is member reference L.key-fragment + * val' is val with ',,' replaced by ',' + * and only R may be empty. + * + * Duplicate keys are permitted; all but the last one are ignored. + * + * The equations must have a solution. Counter-example: a.b=3D1,a=3D2 + * doesn't have one, because R.a must be an object to satisfy a.b=3D1 + * and a string to satisfy a=3D2. + * + * The length of any key-fragment must be between 1 and 127. + * + * Design flaw: there is no way to denote an empty non-root object. + * While interpreting "key absent" as empty object seems natural + * (removing a key-val from the input string removes the member when + * there are more, so why not when it's the last), it doesn't work: + * "key absent" already means "optional object absent", which isn't + * the same as "empty object present". + * + * Additional syntax for use with an implied key: + * + * key-vals-ik =3D val-no-key [ ',' key-vals ] + * val-no-key =3D / [^=3D,]* / + * + * where no-key is syntactic sugar for implied-key=3Dval-no-key. + * + * TODO support lists + * TODO support key-fragment with __RFQDN_ prefix (downstream extensions) + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qmp/qstring.h" +#include "qemu/option.h" + +/* + * Ensure @cur maps @key_in_cur the right way. + * If @value is null, it needs to map to a QDict, else to this + * QString. + * If @cur doesn't have @key_in_cur, put an empty QDict or @value, + * respectively. + * Else, if it needs to map to a QDict, and already does, do nothing. + * Else, if it needs to map to this QString, and already maps to a + * QString, replace it by @value. + * Else, fail because we have conflicting needs on how to map + * @key_in_cur. + * In any case, take over the reference to @value, i.e. if the caller + * wants to hold on to a reference, it needs to QINCREF(). + * Use @key up to @key_cursor to identify the key in error messages. + * On success, return the mapped value. + * On failure, store an error through @errp and return NULL. + */ +static QObject *keyval_parse_put(QDict *cur, + const char *key_in_cur, QString *value, + const char *key, const char *key_cursor, + Error **errp) +{ + QObject *old, *new; + + old =3D qdict_get(cur, key_in_cur); + if (old) { + if (qobject_type(old) !=3D (value ? QTYPE_QSTRING : QTYPE_QDICT)) { + error_setg(errp, "Parameters '%.*s.*' used inconsistently", + (int)(key_cursor - key), key); + QDECREF(value); + return NULL; + } + if (!value) { + return old; /* already QDict, do nothing */ + } + new =3D QOBJECT(value); /* replacement */ + } else { + new =3D QOBJECT(value) ?: QOBJECT(qdict_new()); + } + qdict_put_obj(cur, key_in_cur, new); + return new; +} + +/* + * Parse one KEY=3DVALUE from @params, store result in @qdict. + * The first fragment of KEY applies to @qdict. Subsequent fragments + * apply to nested QDicts, which are created on demand. @implied_key + * is as in keyval_parse(). + * On success, return a pointer to the next KEY=3DVALUE, or else to '\0'. + * On failure, return NULL. + */ +static const char *keyval_parse_one(QDict *qdict, const char *params, + const char *implied_key, + Error **errp) +{ + const char *key, *key_end, *s; + size_t len; + char key_in_cur[128]; + QDict *cur; + QObject *next; + QString *val; + + key =3D params; + len =3D strcspn(params, "=3D,"); + if (implied_key && len && key[len] !=3D '=3D') { + /* Desugar implied key */ + key =3D implied_key; + len =3D strlen(implied_key); + } + key_end =3D key + len; + + /* + * Loop over key fragments: @s points to current fragment, it + * applies to @cur. @key_in_cur[] holds the previous fragment. + */ + cur =3D qdict; + s =3D key; + for (;;) { + for (len =3D 0; s + len < key_end && s[len] !=3D '.'; len++) { + } + if (!len) { + assert(key !=3D implied_key); + error_setg(errp, "Invalid parameter '%.*s'", + (int)(key_end - key), key); + return NULL; + } + if (len >=3D sizeof(key_in_cur)) { + assert(key !=3D implied_key); + error_setg(errp, "Parameter%s '%.*s' is too long", + s !=3D key || s + len !=3D key_end ? " fragment" : = "", + (int)len, s); + return NULL; + } + + if (s !=3D key) { + next =3D keyval_parse_put(cur, key_in_cur, NULL, + key, s - 1, errp); + if (!next) { + return NULL; + } + cur =3D qobject_to_qdict(next); + assert(cur); + } + + memcpy(key_in_cur, s, len); + key_in_cur[len] =3D 0; + s +=3D len; + + if (*s !=3D '.') { + break; + } + s++; + } + + if (key =3D=3D implied_key) { + assert(!*s); + s =3D params; + } else { + if (*s !=3D '=3D') { + error_setg(errp, "Expected '=3D' after parameter '%.*s'", + (int)(s - key), key); + return NULL; + } + s++; + } + + val =3D qstring_new(); + for (;;) { + if (!*s) { + break; + } else if (*s =3D=3D ',') { + s++; + if (*s !=3D ',') { + break; + } + } + qstring_append_chr(val, *s++); + } + + if (!keyval_parse_put(cur, key_in_cur, val, key, key_end, errp)) { + return NULL; + } + return s; +} + +/* + * Parse @params in QEMU's traditional KEY=3DVALUE,... syntax. + * If @implied_key, the first KEY=3D can be omitted. @implied_key is + * implied then, and VALUE can't be empty or contain ',' or '=3D'. + * On success, return a dictionary of the parsed keys and values. + * On failure, store an error through @errp and return NULL. + */ +QDict *keyval_parse(const char *params, const char *implied_key, + Error **errp) +{ + QDict *qdict =3D qdict_new(); + const char *s; + + s =3D params; + while (*s) { + s =3D keyval_parse_one(qdict, s, implied_key, errp); + if (!s) { + QDECREF(qdict); + return NULL; + } + implied_key =3D NULL; + } + + return qdict; +} --=20 2.7.4 From nobody Sun May 5 07:43:36 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 14883216803031003.8593029922984; Tue, 28 Feb 2017 14:41:20 -0800 (PST) Received: from localhost ([::1]:37465 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqSM-0000lU-Rz for importer@patchew.org; Tue, 28 Feb 2017 17:41:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33602) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056c-V0 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDq-0000Wp-UX for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46862) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDq-0000Vl-LO for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:18 -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 D6CA237F1F for ; Tue, 28 Feb 2017 22:26:18 +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 4BC841DCC1; Tue, 28 Feb 2017 22:26:18 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B6C2E1138657; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:55 +0100 Message-Id: <1488320775-9849-5-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26:18 +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] [PULL 04/24] qapi: qobject input visitor variant for use with keyval_parse() 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" From: "Daniel P. Berrange" Currently the QObjectInputVisitor assumes that all scalar values are directly represented as the final types declared by the thing being visited. i.e. it assumes an 'int' is using QInt, and a 'bool' is using QBool, etc. This is good when QObjectInputVisitor is fed a QObject that came from a JSON document on the QMP monitor, as it will strictly validate correctness. To allow QObjectInputVisitor to be reused for visiting a QObject originating from keyval_parse(), an alternative mode is needed where all the scalars types are represented as QString and converted on the fly to the final desired type. Signed-off-by: Daniel P. Berrange Message-Id: <1475246744-29302-8-git-send-email-berrange@redhat.com> Rebased, conflicts resolved, commit message updated to refer to keyval_parse(). autocast replaced by keyval in identifiers, noautocast replaced by fail in tests. Fix qobject_input_type_uint64_keyval() not to reject '-', for QemuOpts compatibility: replace parse_uint_full() by open-coded parse_option_number(). The next commit will add suitable tests. Leave out the fancy ERANGE error reporting for now, but add a TODO comment. Add it qobject_input_type_int64_keyval() and qobject_input_type_number_keyval(), too. Open code parse_option_bool() and parse_option_size() so we have to call qobject_input_get_name() only when actually needed. Again, leave out ERANGE error reporting for now. QAPI/QMP downstream extension prefixes __RFQDN_ don't work, because keyval_parse() splits them at '.'. Add a TODO comment there. qobject_input_type_int64_keyval(), qobject_input_type_uint64_keyval(), qobject_input_type_number_keyval() tweaked for style. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-5-git-send-email-armbru@redhat.com> --- include/qapi/qobject-input-visitor.h | 9 ++ qapi/qobject-input-visitor.c | 166 ++++++++++++++++++++++++++++++- tests/test-qobject-input-visitor.c | 188 +++++++++++++++++++++++++++++++= +++- 3 files changed, 358 insertions(+), 5 deletions(-) diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-in= put-visitor.h index 0b7633a..282f9d2 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -59,4 +59,13 @@ typedef struct QObjectInputVisitor QObjectInputVisitor; */ Visitor *qobject_input_visitor_new(QObject *obj); =20 +/* + * Create a QObject input visitor for @obj for use with keyval_parse() + * + * This is like qobject_input_visitor_new(), except scalars are all + * QString, and error messages refer to parts of @obj in the syntax + * keyval_parse() uses for KEYs. + */ +Visitor *qobject_input_visitor_new_keyval(QObject *obj); + #endif diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index d192727..e2e3e70 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -1,7 +1,7 @@ /* * Input Visitor * - * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright (C) 2012-2017 Red Hat, Inc. * Copyright IBM, Corp. 2011 * * Authors: @@ -20,6 +20,7 @@ #include "qemu-common.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" +#include "qemu/cutils.h" =20 typedef struct StackObject { const char *name; /* Name of @obj in its parent, if any */ @@ -337,6 +338,31 @@ static void qobject_input_type_int64(Visitor *v, const= char *name, int64_t *obj, *obj =3D qint_get_int(qint); } =20 + +static void qobject_input_type_int64_keyval(Visitor *v, const char *name, + int64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + + if (!qobj) { + return; + } + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return; + } + + if (qemu_strtoi64(qstring_get_str(qstr), NULL, 0, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "integer"); + } +} + static void qobject_input_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) { @@ -358,6 +384,30 @@ static void qobject_input_type_uint64(Visitor *v, cons= t char *name, *obj =3D qint_get_int(qint); } =20 +static void qobject_input_type_uint64_keyval(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + + if (!qobj) { + return; + } + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return; + } + + if (qemu_strtou64(qstring_get_str(qstr), NULL, 0, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "integer"); + } +} + static void qobject_input_type_bool(Visitor *v, const char *name, bool *ob= j, Error **errp) { @@ -378,6 +428,35 @@ static void qobject_input_type_bool(Visitor *v, const = char *name, bool *obj, *obj =3D qbool_get_bool(qbool); } =20 +static void qobject_input_type_bool_keyval(Visitor *v, const char *name, + bool *obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + const char *str; + + if (!qobj) { + return; + } + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return; + } + + str =3D qstring_get_str(qstr); + if (!strcmp(str, "on")) { + *obj =3D true; + } else if (!strcmp(str, "off")) { + *obj =3D false; + } else { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "'on' or 'off'"); + } +} + static void qobject_input_type_str(Visitor *v, const char *name, char **ob= j, Error **errp) { @@ -426,6 +505,35 @@ static void qobject_input_type_number(Visitor *v, cons= t char *name, double *obj, full_name(qiv, name), "number"); } =20 +static void qobject_input_type_number_keyval(Visitor *v, const char *name, + double *obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + const char *str; + char *endp; + + if (!qobj) { + return; + } + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return; + } + + str =3D qstring_get_str(qstr); + errno =3D 0; + *obj =3D strtod(str, &endp); + if (errno || endp =3D=3D str || *endp) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "number"); + } +} + static void qobject_input_type_any(Visitor *v, const char *name, QObject *= *obj, Error **errp) { @@ -456,6 +564,30 @@ static void qobject_input_type_null(Visitor *v, const = char *name, Error **errp) } } =20 +static void qobject_input_type_size_keyval(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + + if (!qobj) { + return; + } + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return; + } + + if (qemu_strtosz(qstring_get_str(qstr), NULL, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "size"); + } +} + static void qobject_input_optional(Visitor *v, const char *name, bool *pre= sent) { QObjectInputVisitor *qiv =3D to_qiv(v); @@ -518,3 +650,35 @@ Visitor *qobject_input_visitor_new(QObject *obj) =20 return &v->visitor; } + +Visitor *qobject_input_visitor_new_keyval(QObject *obj) +{ + QObjectInputVisitor *v; + + v =3D g_malloc0(sizeof(*v)); + + v->visitor.type =3D VISITOR_INPUT; + v->visitor.start_struct =3D qobject_input_start_struct; + v->visitor.check_struct =3D qobject_input_check_struct; + 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_keyval; + v->visitor.type_uint64 =3D qobject_input_type_uint64_keyval; + v->visitor.type_bool =3D qobject_input_type_bool_keyval; + v->visitor.type_str =3D qobject_input_type_str; + v->visitor.type_number =3D qobject_input_type_number_keyval; + v->visitor.type_any =3D qobject_input_type_any; + v->visitor.type_null =3D qobject_input_type_null; + v->visitor.type_size =3D qobject_input_type_size_keyval; + v->visitor.optional =3D qobject_input_optional; + v->visitor.free =3D qobject_input_free; + + v->root =3D obj; + qobject_incref(obj); + + return &v->visitor; +} diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 94305f5..32ba492 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -45,6 +45,7 @@ static void visitor_input_teardown(TestInputVisitorData *= data, function so that the JSON string used by the tests are kept in the test functions (and not in main()). */ static Visitor *visitor_input_test_init_internal(TestInputVisitorData *dat= a, + bool keyval, const char *json_string, va_list *ap) { @@ -53,11 +54,29 @@ static Visitor *visitor_input_test_init_internal(TestIn= putVisitorData *data, data->obj =3D qobject_from_jsonv(json_string, ap); g_assert(data->obj); =20 - data->qiv =3D qobject_input_visitor_new(data->obj); + if (keyval) { + data->qiv =3D qobject_input_visitor_new_keyval(data->obj); + } else { + data->qiv =3D qobject_input_visitor_new(data->obj); + } g_assert(data->qiv); return data->qiv; } =20 +static GCC_FMT_ATTR(3, 4) +Visitor *visitor_input_test_init_full(TestInputVisitorData *data, + bool keyval, + const char *json_string, ...) +{ + Visitor *v; + va_list ap; + + va_start(ap, json_string); + v =3D visitor_input_test_init_internal(data, keyval, json_string, &ap); + va_end(ap); + return v; +} + static GCC_FMT_ATTR(2, 3) Visitor *visitor_input_test_init(TestInputVisitorData *data, const char *json_string, ...) @@ -66,7 +85,7 @@ Visitor *visitor_input_test_init(TestInputVisitorData *da= ta, va_list ap; =20 va_start(ap, json_string); - v =3D visitor_input_test_init_internal(data, json_string, &ap); + v =3D visitor_input_test_init_internal(data, false, json_string, &ap); va_end(ap); return v; } @@ -81,7 +100,7 @@ Visitor *visitor_input_test_init(TestInputVisitorData *d= ata, static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data, const char *json_string) { - return visitor_input_test_init_internal(data, json_string, NULL); + return visitor_input_test_init_internal(data, false, json_string, NULL= ); } =20 static void test_visitor_in_int(TestInputVisitorData *data, @@ -114,6 +133,43 @@ static void test_visitor_in_int_overflow(TestInputVisi= torData *data, error_free_or_abort(&err); } =20 +static void test_visitor_in_int_keyval(TestInputVisitorData *data, + const void *unused) +{ + int64_t res =3D 0, value =3D -42; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "%" PRId64, value); + visit_type_int(v, NULL, &res, &err); + error_free_or_abort(&err); +} + +static void test_visitor_in_int_str_keyval(TestInputVisitorData *data, + const void *unused) +{ + int64_t res =3D 0, value =3D -42; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "\"-42\""); + + visit_type_int(v, NULL, &res, &error_abort); + g_assert_cmpint(res, =3D=3D, value); +} + +static void test_visitor_in_int_str_fail(TestInputVisitorData *data, + const void *unused) +{ + int64_t res =3D 0; + Visitor *v; + Error *err =3D NULL; + + v =3D visitor_input_test_init(data, "\"-42\""); + + visit_type_int(v, NULL, &res, &err); + error_free_or_abort(&err); +} + static void test_visitor_in_bool(TestInputVisitorData *data, const void *unused) { @@ -126,6 +182,44 @@ static void test_visitor_in_bool(TestInputVisitorData = *data, g_assert_cmpint(res, =3D=3D, true); } =20 +static void test_visitor_in_bool_keyval(TestInputVisitorData *data, + const void *unused) +{ + bool res =3D false; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "true"); + + visit_type_bool(v, NULL, &res, &err); + error_free_or_abort(&err); +} + +static void test_visitor_in_bool_str_keyval(TestInputVisitorData *data, + const void *unused) +{ + bool res =3D false; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "\"on\""); + + visit_type_bool(v, NULL, &res, &error_abort); + g_assert_cmpint(res, =3D=3D, true); +} + +static void test_visitor_in_bool_str_fail(TestInputVisitorData *data, + const void *unused) +{ + bool res =3D false; + Visitor *v; + Error *err =3D NULL; + + v =3D visitor_input_test_init(data, "\"true\""); + + visit_type_bool(v, NULL, &res, &err); + error_free_or_abort(&err); +} + static void test_visitor_in_number(TestInputVisitorData *data, const void *unused) { @@ -138,6 +232,69 @@ static void test_visitor_in_number(TestInputVisitorDat= a *data, g_assert_cmpfloat(res, =3D=3D, value); } =20 +static void test_visitor_in_number_keyval(TestInputVisitorData *data, + const void *unused) +{ + double res =3D 0, value =3D 3.14; + Error *err =3D NULL; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "%f", value); + + visit_type_number(v, NULL, &res, &err); + error_free_or_abort(&err); +} + +static void test_visitor_in_number_str_keyval(TestInputVisitorData *data, + const void *unused) +{ + double res =3D 0, value =3D 3.14; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "\"3.14\""); + + visit_type_number(v, NULL, &res, &error_abort); + g_assert_cmpfloat(res, =3D=3D, value); +} + +static void test_visitor_in_number_str_fail(TestInputVisitorData *data, + const void *unused) +{ + double res =3D 0; + Visitor *v; + Error *err =3D NULL; + + v =3D visitor_input_test_init(data, "\"3.14\""); + + visit_type_number(v, NULL, &res, &err); + error_free_or_abort(&err); +} + +static void test_visitor_in_size_str_keyval(TestInputVisitorData *data, + const void *unused) +{ + uint64_t res, value =3D 500 * 1024 * 1024; + Visitor *v; + + v =3D visitor_input_test_init_full(data, true, "\"500M\""); + + visit_type_size(v, NULL, &res, &error_abort); + g_assert_cmpfloat(res, =3D=3D, value); +} + +static void test_visitor_in_size_str_fail(TestInputVisitorData *data, + const void *unused) +{ + uint64_t res =3D 0; + Visitor *v; + Error *err =3D NULL; + + v =3D visitor_input_test_init(data, "\"500M\""); + + visit_type_size(v, NULL, &res, &err); + error_free_or_abort(&err); +} + static void test_visitor_in_string(TestInputVisitorData *data, const void *unused) { @@ -294,7 +451,8 @@ static void test_visitor_in_null(TestInputVisitorData *= data, * when input is not null. */ =20 - v =3D visitor_input_test_init(data, "{ 'a': null, 'b': '', 'c': null }= "); + v =3D visitor_input_test_init_full(data, false, + "{ 'a': null, 'b': '' }"); visit_start_struct(v, NULL, NULL, 0, &error_abort); visit_type_null(v, "a", &error_abort); visit_type_null(v, "b", &err); @@ -1069,10 +1227,32 @@ int main(int argc, char **argv) NULL, test_visitor_in_int); input_visitor_test_add("/visitor/input/int_overflow", NULL, test_visitor_in_int_overflow); + input_visitor_test_add("/visitor/input/int_keyval", + NULL, test_visitor_in_int_keyval); + input_visitor_test_add("/visitor/input/int_str_keyval", + NULL, test_visitor_in_int_str_keyval); + input_visitor_test_add("/visitor/input/int_str_fail", + NULL, test_visitor_in_int_str_fail); input_visitor_test_add("/visitor/input/bool", NULL, test_visitor_in_bool); + input_visitor_test_add("/visitor/input/bool_keyval", + NULL, test_visitor_in_bool_keyval); + input_visitor_test_add("/visitor/input/bool_str_keyval", + NULL, test_visitor_in_bool_str_keyval); + input_visitor_test_add("/visitor/input/bool_str_fail", + NULL, test_visitor_in_bool_str_fail); input_visitor_test_add("/visitor/input/number", NULL, test_visitor_in_number); + input_visitor_test_add("/visitor/input/number_keyval", + NULL, test_visitor_in_number_keyval); + input_visitor_test_add("/visitor/input/number_str_keyval", + NULL, test_visitor_in_number_str_keyval); + input_visitor_test_add("/visitor/input/number_str_fail", + NULL, test_visitor_in_number_str_fail); + input_visitor_test_add("/visitor/input/size_str_keyval", + NULL, test_visitor_in_size_str_keyval); + input_visitor_test_add("/visitor/input/size_str_fail", + NULL, test_visitor_in_size_str_fail); input_visitor_test_add("/visitor/input/string", NULL, test_visitor_in_string); input_visitor_test_add("/visitor/input/enum", --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321424549888.9979040470544; Tue, 28 Feb 2017 14:37:04 -0800 (PST) Received: from localhost ([::1]:37435 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqOF-0005DW-2n for importer@patchew.org; Tue, 28 Feb 2017 17:37:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33795) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDy-0005AZ-GX for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000Yb-F0 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46870) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xd-78 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 6A8B237F1F for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQI7a017516 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:19 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id B9DFC11386CE; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:56 +0100 Message-Id: <1488320775-9849-6-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.29]); Tue, 28 Feb 2017 22:26: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] [PULL 05/24] test-keyval: Cover use with 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" Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-6-git-send-email-armbru@redhat.com> --- tests/test-keyval.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 312 insertions(+) diff --git a/tests/test-keyval.c b/tests/test-keyval.c index 27f6625..1c2aeea 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -12,6 +12,8 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qobject-input-visitor.h" +#include "qemu/cutils.h" #include "qemu/option.h" =20 static void test_keyval_parse(void) @@ -171,10 +173,320 @@ static void test_keyval_parse(void) g_assert(!qdict); } =20 +static void test_keyval_visit_bool(void) +{ + Error *err =3D NULL; + Visitor *v; + QDict *qdict; + bool b; + + qdict =3D keyval_parse("bool1=3Don,bool2=3Doff", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_bool(v, "bool1", &b, &error_abort); + g_assert(b); + visit_type_bool(v, "bool2", &b, &error_abort); + g_assert(!b); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + qdict =3D keyval_parse("bool1=3Doffer", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_bool(v, "bool1", &b, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); +} + +static void test_keyval_visit_number(void) +{ + Error *err =3D NULL; + Visitor *v; + QDict *qdict; + uint64_t u; + + /* Lower limit zero */ + qdict =3D keyval_parse("number1=3D0", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &error_abort); + g_assert_cmpuint(u, =3D=3D, 0); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Upper limit 2^64-1 */ + qdict =3D keyval_parse("number1=3D18446744073709551615,number2=3D-1", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &error_abort); + g_assert_cmphex(u, =3D=3D, UINT64_MAX); + visit_type_uint64(v, "number2", &u, &error_abort); + g_assert_cmphex(u, =3D=3D, UINT64_MAX); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Above upper limit */ + qdict =3D keyval_parse("number1=3D18446744073709551616", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); + + /* Below lower limit */ + qdict =3D keyval_parse("number1=3D-18446744073709551616", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); + + /* Hex and octal */ + qdict =3D keyval_parse("number1=3D0x2a,number2=3D052", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &error_abort); + g_assert_cmpuint(u, =3D=3D, 42); + visit_type_uint64(v, "number2", &u, &error_abort); + g_assert_cmpuint(u, =3D=3D, 42); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Trailing crap */ + qdict =3D keyval_parse("number1=3D3.14,number2=3D08", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_uint64(v, "number1", &u, &err); + error_free_or_abort(&err); + visit_type_uint64(v, "number2", &u, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); +} + +static void test_keyval_visit_size(void) +{ + Error *err =3D NULL; + Visitor *v; + QDict *qdict; + uint64_t sz; + + /* Lower limit zero */ + qdict =3D keyval_parse("sz1=3D0", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmpuint(sz, =3D=3D, 0); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Note: precision is 53 bits since we're parsing with strtod() */ + + /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */ + qdict =3D keyval_parse("sz1=3D9007199254740991," + "sz2=3D9007199254740992," + "sz3=3D9007199254740993", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0x1fffffffffffff); + visit_type_size(v, "sz2", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0x20000000000000); + visit_type_size(v, "sz3", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0x20000000000000); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ + qdict =3D keyval_parse("sz1=3D9223372036854774784," /* 7ffffffffffffc0= 0 */ + "sz2=3D9223372036854775295", /* 7ffffffffffffdff = */ + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0x7ffffffffffffc00); + visit_type_size(v, "sz2", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0x7ffffffffffffc00); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ + qdict =3D keyval_parse("sz1=3D18446744073709549568," /* fffffffffffff8= 00 */ + "sz2=3D18446744073709550591", /* fffffffffffffbff= */ + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0xfffffffffffff800); + visit_type_size(v, "sz2", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 0xfffffffffffff800); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Beyond limits */ + qdict =3D keyval_parse("sz1=3D-1," + "sz2=3D18446744073709550592", /* fffffffffffffc00= */ + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &err); + error_free_or_abort(&err); + visit_type_size(v, "sz2", &sz, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); + + /* Suffixes */ + qdict =3D keyval_parse("sz1=3D8b,sz2=3D1.5k,sz3=3D2M,sz4=3D0.1G,sz5=3D= 16777215T", + NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmpuint(sz, =3D=3D, 8); + visit_type_size(v, "sz2", &sz, &error_abort); + g_assert_cmpuint(sz, =3D=3D, 1536); + visit_type_size(v, "sz3", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 2 * M_BYTE); + visit_type_size(v, "sz4", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, G_BYTE / 10); + visit_type_size(v, "sz5", &sz, &error_abort); + g_assert_cmphex(sz, =3D=3D, 16777215 * T_BYTE); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Beyond limit with suffix */ + qdict =3D keyval_parse("sz1=3D16777216T", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); + + /* Trailing crap */ + qdict =3D keyval_parse("sz1=3D16E,sz2=3D16Gi", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &err); + error_free_or_abort(&err); + visit_type_size(v, "sz2", &sz, &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); + visit_free(v); +} + +static void test_keyval_visit_dict(void) +{ + Error *err =3D NULL; + Visitor *v; + QDict *qdict; + int64_t i; + + qdict =3D keyval_parse("a.b.c=3D1,a.b.c=3D2,d=3D3", NULL, &error_abort= ); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_struct(v, "a", NULL, 0, &error_abort); + visit_start_struct(v, "b", NULL, 0, &error_abort); + visit_type_int(v, "c", &i, &error_abort); + g_assert_cmpint(i, =3D=3D, 2); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_type_int(v, "d", &i, &error_abort); + g_assert_cmpint(i, =3D=3D, 3); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + qdict =3D keyval_parse("a.b=3D", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_struct(v, "a", NULL, 0, &error_abort); + visit_type_int(v, "c", &i, &err); /* a.c missing */ + error_free_or_abort(&err); + visit_check_struct(v, &err); + error_free_or_abort(&err); /* a.b unexpected */ + visit_end_struct(v, NULL); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); +} + +static void test_keyval_visit_optional(void) +{ + Visitor *v; + QDict *qdict; + bool present; + int64_t i; + + qdict =3D keyval_parse("a.b=3D1", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_optional(v, "b", &present); + g_assert(!present); /* b missing */ + visit_optional(v, "a", &present); + g_assert(present); /* a present */ + visit_start_struct(v, "a", NULL, 0, &error_abort); + visit_optional(v, "b", &present); + g_assert(present); /* a.b present */ + visit_type_int(v, "b", &i, &error_abort); + g_assert_cmpint(i, =3D=3D, 1); + visit_optional(v, "a", &present); + g_assert(!present); /* a.a missing */ + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); +} + int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func("/keyval/keyval_parse", test_keyval_parse); + g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool); + g_test_add_func("/keyval/visit/number", test_keyval_visit_number); + g_test_add_func("/keyval/visit/size", test_keyval_visit_size); + g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict); + g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); g_test_run(); return 0; } --=20 2.7.4 From nobody Sun May 5 07:43:36 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 14883211645141023.1477865159949; Tue, 28 Feb 2017 14:32:44 -0800 (PST) Received: from localhost ([::1]:37410 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqJy-0001Pt-Qg for importer@patchew.org; Tue, 28 Feb 2017 17:32:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056e-Ve for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000YF-Cv for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38630) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000XW-34 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 49D378047C for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQIY7017518 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:19 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id BCEF011386DC; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:57 +0100 Message-Id: <1488320775-9849-7-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26: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] [PULL 06/24] qapi: Factor out common part of qobject input visitor creation 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: Kevin Wolf Message-Id: <1488317230-26248-7-git-send-email-armbru@redhat.com> --- qapi/qobject-input-visitor.c | 61 +++++++++++++++++++---------------------= ---- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index e2e3e70..270033e 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -619,22 +619,34 @@ static void qobject_input_free(Visitor *v) g_free(qiv); } =20 +static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj) +{ + QObjectInputVisitor *v =3D g_malloc0(sizeof(*v)); + + assert(obj); + + v->visitor.type =3D VISITOR_INPUT; + v->visitor.start_struct =3D qobject_input_start_struct; + v->visitor.check_struct =3D qobject_input_check_struct; + 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.optional =3D qobject_input_optional; + v->visitor.free =3D qobject_input_free; + + v->root =3D obj; + qobject_incref(obj); + + return v; +} + Visitor *qobject_input_visitor_new(QObject *obj) { - QObjectInputVisitor *v; + QObjectInputVisitor *v =3D qobject_input_visitor_base_new(obj); =20 - assert(obj); - v =3D g_malloc0(sizeof(*v)); - - v->visitor.type =3D VISITOR_INPUT; - v->visitor.start_struct =3D qobject_input_start_struct; - v->visitor.check_struct =3D qobject_input_check_struct; - 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; v->visitor.type_uint64 =3D qobject_input_type_uint64; v->visitor.type_bool =3D qobject_input_type_bool; @@ -642,30 +654,14 @@ Visitor *qobject_input_visitor_new(QObject *obj) v->visitor.type_number =3D qobject_input_type_number; v->visitor.type_any =3D qobject_input_type_any; v->visitor.type_null =3D qobject_input_type_null; - v->visitor.optional =3D qobject_input_optional; - v->visitor.free =3D qobject_input_free; - - v->root =3D obj; - qobject_incref(obj); =20 return &v->visitor; } =20 Visitor *qobject_input_visitor_new_keyval(QObject *obj) { - QObjectInputVisitor *v; + QObjectInputVisitor *v =3D qobject_input_visitor_base_new(obj); =20 - v =3D g_malloc0(sizeof(*v)); - - v->visitor.type =3D VISITOR_INPUT; - v->visitor.start_struct =3D qobject_input_start_struct; - v->visitor.check_struct =3D qobject_input_check_struct; - 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_keyval; v->visitor.type_uint64 =3D qobject_input_type_uint64_keyval; v->visitor.type_bool =3D qobject_input_type_bool_keyval; @@ -674,11 +670,6 @@ Visitor *qobject_input_visitor_new_keyval(QObject *obj) v->visitor.type_any =3D qobject_input_type_any; v->visitor.type_null =3D qobject_input_type_null; v->visitor.type_size =3D qobject_input_type_size_keyval; - v->visitor.optional =3D qobject_input_optional; - v->visitor.free =3D qobject_input_free; - - v->root =3D obj; - qobject_incref(obj); =20 return &v->visitor; } --=20 2.7.4 From nobody Sun May 5 07:43:36 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 148832084532373.21723750232661; Tue, 28 Feb 2017 14:27:25 -0800 (PST) Received: from localhost ([::1]:37378 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqEu-0005AH-4K for importer@patchew.org; Tue, 28 Feb 2017 17:27:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33607) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056f-WC for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000YG-CC for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56640) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000XV-38 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 499E3C049D5C for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQIge017519 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:19 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id BFE1011385E0; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:58 +0100 Message-Id: <1488320775-9849-8-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.31]); Tue, 28 Feb 2017 22:26: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] [PULL 07/24] qapi: Factor out common qobject_input_get_keyval() 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 Message-Id: <1488317230-26248-8-git-send-email-armbru@redhat.com> --- qapi/qobject-input-visitor.c | 87 ++++++++++++++++++----------------------= ---- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 270033e..6c56040 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -151,6 +151,28 @@ static QObject *qobject_input_get_object(QObjectInputV= isitor *qiv, return obj; } =20 +static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv, + const char *name, + Error **errp) +{ + QObject *qobj; + QString *qstr; + + qobj =3D qobject_input_get_object(qiv, name, true, errp); + if (!qobj) { + return NULL; + } + + qstr =3D qobject_to_qstring(qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return NULL; + } + + return qstring_get_str(qstr); +} + static void qdict_add_key(const char *key, QObject *obj, void *opaque) { GHashTable *h =3D opaque; @@ -343,20 +365,13 @@ static void qobject_input_type_int64_keyval(Visitor *= v, const char *name, int64_t *obj, Error **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - QString *qstr; + const char *str =3D qobject_input_get_keyval(qiv, name, errp); =20 - if (!qobj) { - return; - } - qstr =3D qobject_to_qstring(qobj); - if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); + if (!str) { return; } =20 - if (qemu_strtoi64(qstring_get_str(qstr), NULL, 0, obj) < 0) { + if (qemu_strtoi64(str, NULL, 0, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "integer"); @@ -388,20 +403,13 @@ static void qobject_input_type_uint64_keyval(Visitor = *v, const char *name, uint64_t *obj, Error **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - QString *qstr; + const char *str =3D qobject_input_get_keyval(qiv, name, errp); =20 - if (!qobj) { - return; - } - qstr =3D qobject_to_qstring(qobj); - if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); + if (!str) { return; } =20 - if (qemu_strtou64(qstring_get_str(qstr), NULL, 0, obj) < 0) { + if (qemu_strtou64(str, NULL, 0, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "integer"); @@ -432,21 +440,12 @@ static void qobject_input_type_bool_keyval(Visitor *v= , const char *name, bool *obj, Error **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - QString *qstr; - const char *str; + const char *str =3D qobject_input_get_keyval(qiv, name, errp); =20 - if (!qobj) { - return; - } - qstr =3D qobject_to_qstring(qobj); - if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); + if (!str) { return; } =20 - str =3D qstring_get_str(qstr); if (!strcmp(str, "on")) { *obj =3D true; } else if (!strcmp(str, "off")) { @@ -509,22 +508,13 @@ static void qobject_input_type_number_keyval(Visitor = *v, const char *name, double *obj, Error **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - QString *qstr; - const char *str; + const char *str =3D qobject_input_get_keyval(qiv, name, errp); char *endp; =20 - if (!qobj) { - return; - } - qstr =3D qobject_to_qstring(qobj); - if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); + if (!str) { return; } =20 - str =3D qstring_get_str(qstr); errno =3D 0; *obj =3D strtod(str, &endp); if (errno || endp =3D=3D str || *endp) { @@ -568,20 +558,13 @@ static void qobject_input_type_size_keyval(Visitor *v= , const char *name, uint64_t *obj, Error **errp) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_get_object(qiv, name, true, errp); - QString *qstr; + const char *str =3D qobject_input_get_keyval(qiv, name, errp); =20 - if (!qobj) { - return; - } - qstr =3D qobject_to_qstring(qobj); - if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); + if (!str) { return; } =20 - if (qemu_strtosz(qstring_get_str(qstr), NULL, obj) < 0) { + if (qemu_strtosz(str, NULL, obj) < 0) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, full_name(qiv, name), "size"); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321048350487.19561889889974; Tue, 28 Feb 2017 14:30:48 -0800 (PST) Received: from localhost ([::1]:37396 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqIB-00089x-0l for importer@patchew.org; Tue, 28 Feb 2017 17:30:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33612) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDu-00056i-1K for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000Y8-BH for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56644) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xb-33 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 51D1AC0016BC for ; Tue, 28 Feb 2017 22:26: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 v1SMQIaM011091 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:19 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C2DB211385E1; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:25:59 +0100 Message-Id: <1488320775-9849-9-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26: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] [PULL 08/24] qobject: Propagate parse errors through qobject_from_jsonv() 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 few commits will put the errors to use where appropriate. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-9-git-send-email-armbru@redhat.com> --- include/qapi/qmp/qjson.h | 3 ++- qobject/qjson.c | 12 ++++++++---- tests/libqtest.c | 2 +- tests/test-qobject-input-visitor.c | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h index 02b1f2c..6fe42d0 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -19,7 +19,8 @@ =20 QObject *qobject_from_json(const char *string); QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); -QObject *qobject_from_jsonv(const char *string, va_list *ap) GCC_FMT_ATTR(= 1, 0); +QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) + GCC_FMT_ATTR(1, 0); =20 QString *qobject_to_json(const QObject *obj); QString *qobject_to_json_pretty(const QObject *obj); diff --git a/qobject/qjson.c b/qobject/qjson.c index 9a0de89..339c9f7 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -12,6 +12,7 @@ */ =20 #include "qemu/osdep.h" +#include "qapi/error.h" #include "qapi/qmp/json-lexer.h" #include "qapi/qmp/json-parser.h" #include "qapi/qmp/json-streamer.h" @@ -24,15 +25,17 @@ typedef struct JSONParsingState JSONMessageParser parser; va_list *ap; QObject *result; + Error *err; } JSONParsingState; =20 static void parse_json(JSONMessageParser *parser, GQueue *tokens) { JSONParsingState *s =3D container_of(parser, JSONParsingState, parser); - s->result =3D json_parser_parse(tokens, s->ap); + + s->result =3D json_parser_parse_err(tokens, s->ap, &s->err); } =20 -QObject *qobject_from_jsonv(const char *string, va_list *ap) +QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) { JSONParsingState state =3D {}; =20 @@ -43,12 +46,13 @@ QObject *qobject_from_jsonv(const char *string, va_list= *ap) json_message_parser_flush(&state.parser); json_message_parser_destroy(&state.parser); =20 + error_propagate(errp, state.err); return state.result; } =20 QObject *qobject_from_json(const char *string) { - return qobject_from_jsonv(string, NULL); + return qobject_from_jsonv(string, NULL, NULL); } =20 /* @@ -61,7 +65,7 @@ QObject *qobject_from_jsonf(const char *string, ...) va_list ap; =20 va_start(ap, string); - obj =3D qobject_from_jsonv(string, &ap); + obj =3D qobject_from_jsonv(string, &ap, NULL); va_end(ap); =20 assert(obj !=3D NULL); diff --git a/tests/libqtest.c b/tests/libqtest.c index cf27afc..683d5e3 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -442,7 +442,7 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) * is an array type. */ va_copy(ap_copy, ap); - qobj =3D qobject_from_jsonv(fmt, &ap_copy); + qobj =3D qobject_from_jsonv(fmt, &ap_copy, NULL); va_end(ap_copy); =20 /* No need to send anything for an empty QObject. */ diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 32ba492..36cc4b5 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -51,7 +51,7 @@ static Visitor *visitor_input_test_init_internal(TestInpu= tVisitorData *data, { visitor_input_teardown(data, NULL); =20 - data->obj =3D qobject_from_jsonv(json_string, ap); + data->obj =3D qobject_from_jsonv(json_string, ap, NULL); g_assert(data->obj); =20 if (keyval) { --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488320918670989.5540979994541; Tue, 28 Feb 2017 14:28:38 -0800 (PST) Received: from localhost ([::1]:37388 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqG3-0006F6-JS for importer@patchew.org; Tue, 28 Feb 2017 17:28:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33594) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056R-RL for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xz-9I for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48612) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000XT-2x for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 4890F5455D for ; Tue, 28 Feb 2017 22:26: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 1620D1DCC0 for ; Tue, 28 Feb 2017 22:26:20 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C5FD211385ED; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:00 +0100 Message-Id: <1488320775-9849-10-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26: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] [PULL 09/24] libqtest: Fix qmp() & friends to abort on JSON parse errors 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: Kevin Wolf Message-Id: <1488317230-26248-10-git-send-email-armbru@redhat.com> --- tests/libqtest.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 683d5e3..bb444d5 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -21,6 +21,7 @@ #include #include =20 +#include "qapi/error.h" #include "qapi/qmp/json-parser.h" #include "qapi/qmp/json-streamer.h" #include "qapi/qmp/qjson.h" @@ -442,7 +443,7 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) * is an array type. */ va_copy(ap_copy, ap); - qobj =3D qobject_from_jsonv(fmt, &ap_copy, NULL); + qobj =3D qobject_from_jsonv(fmt, &ap_copy, &error_abort); va_end(ap_copy); =20 /* No need to send anything for an empty QObject. */ --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321012849716.6951384315557; Tue, 28 Feb 2017 14:30:12 -0800 (PST) Received: from localhost ([::1]:37395 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqHb-0007gM-Gq for importer@patchew.org; Tue, 28 Feb 2017 17:30:11 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDt-00056V-T0 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xu-83 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46932) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000XX-2r for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 4C5A2C057FA5 for ; Tue, 28 Feb 2017 22:26: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 18BF71DCC1 for ; Tue, 28 Feb 2017 22:26:20 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id C8F2D11385F0; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:01 +0100 Message-Id: <1488320775-9849-11-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.32]); Tue, 28 Feb 2017 22:26: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] [PULL 10/24] qjson: Abort earlier on qobject_from_jsonf() misuse 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" Ignoring errors first, then asserting success is suboptimal. Pass &error_abort instead, so we abort earlier, and hopefully get more useful clues on what's wrong. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-11-git-send-email-armbru@redhat.com> --- qobject/qjson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qobject/qjson.c b/qobject/qjson.c index 339c9f7..c98d6a7 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -65,7 +65,7 @@ QObject *qobject_from_jsonf(const char *string, ...) va_list ap; =20 va_start(ap, string); - obj =3D qobject_from_jsonv(string, &ap, NULL); + obj =3D qobject_from_jsonv(string, &ap, &error_abort); va_end(ap); =20 assert(obj !=3D NULL); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321203395427.00026717380524; Tue, 28 Feb 2017 14:33:23 -0800 (PST) Received: from localhost ([::1]:37411 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqKg-0002Mq-0c for importer@patchew.org; Tue, 28 Feb 2017 17:33:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33640) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDu-00057O-TO for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000YP-Dw for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46934) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xf-85 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 732D6C057FA9 for ; Tue, 28 Feb 2017 22:26: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 v1SMQJdQ011096 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CBC4E11385FC; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:02 +0100 Message-Id: <1488320775-9849-12-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.32]); Tue, 28 Feb 2017 22:26: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] [PULL 11/24] test-qobject-input-visitor: Abort earlier on bad test 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" visitor_input_test_init_internal() parses test input with qobject_from_jsonv(), and asserts it succeeds. Pass &error_abort for good measure. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-12-git-send-email-armbru@redhat.com> --- tests/test-qobject-input-visitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 36cc4b5..6eb48fe 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -51,7 +51,7 @@ static Visitor *visitor_input_test_init_internal(TestInpu= tVisitorData *data, { visitor_input_teardown(data, NULL); =20 - data->obj =3D qobject_from_jsonv(json_string, ap, NULL); + data->obj =3D qobject_from_jsonv(json_string, ap, &error_abort); g_assert(data->obj); =20 if (keyval) { --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321135150692.4464292919897; Tue, 28 Feb 2017 14:32:15 -0800 (PST) Received: from localhost ([::1]:37407 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqJZ-000170-Of for importer@patchew.org; Tue, 28 Feb 2017 17:32:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33754) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDx-00059p-QS for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000Ys-OA for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39812) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xj-F4 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 A110461D03 for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQJrK026274 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CEC6A1138604; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:03 +0100 Message-Id: <1488320775-9849-13-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26: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] [PULL 12/24] qobject: Propagate parse errors through qobject_from_json() 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 few commits will put the errors to use where appropriate. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Reviewed-by: Eric Blake Message-Id: <1488317230-26248-13-git-send-email-armbru@redhat.com> --- block.c | 2 +- include/qapi/qmp/qjson.h | 2 +- monitor.c | 2 +- qobject/qjson.c | 4 +-- tests/check-qjson.c | 62 +++++++++++++++++++---------------= ---- tests/test-visitor-serialization.c | 2 +- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/block.c b/block.c index b663204..af1014f 100644 --- a/block.c +++ b/block.c @@ -1200,7 +1200,7 @@ static QDict *parse_json_filename(const char *filenam= e, Error **errp) ret =3D strstart(filename, "json:", &filename); assert(ret); =20 - options_obj =3D qobject_from_json(filename); + options_obj =3D qobject_from_json(filename, NULL); if (!options_obj) { error_setg(errp, "Could not parse the JSON options"); return NULL; diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h index 6fe42d0..6e84082 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -17,7 +17,7 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" =20 -QObject *qobject_from_json(const char *string); +QObject *qobject_from_json(const char *string, Error **errp); QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) GCC_FMT_ATTR(1, 0); diff --git a/monitor.c b/monitor.c index 97b73ab..858bcda 100644 --- a/monitor.c +++ b/monitor.c @@ -950,7 +950,7 @@ EventInfoList *qmp_query_events(Error **errp) static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, Error **errp) { - *ret_data =3D qobject_from_json(qmp_schema_json); + *ret_data =3D qobject_from_json(qmp_schema_json, NULL); } =20 /* diff --git a/qobject/qjson.c b/qobject/qjson.c index c98d6a7..b2f3bfe 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -50,9 +50,9 @@ QObject *qobject_from_jsonv(const char *string, va_list *= ap, Error **errp) return state.result; } =20 -QObject *qobject_from_json(const char *string) +QObject *qobject_from_json(const char *string, Error **errp) { - return qobject_from_jsonv(string, NULL, NULL); + return qobject_from_jsonv(string, NULL, errp); } =20 /* diff --git a/tests/check-qjson.c b/tests/check-qjson.c index e6d6935..aa63758 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -53,7 +53,7 @@ static void escaped_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); str =3D qobject_to_qstring(obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, test_cases[i].decode= d); @@ -85,7 +85,7 @@ static void simple_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); str =3D qobject_to_qstring(obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -116,7 +116,7 @@ static void single_quote_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); str =3D qobject_to_qstring(obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -809,7 +809,7 @@ static void utf8_string(void) utf8_in =3D test_cases[i].utf8_in ?: test_cases[i].utf8_out; json_out =3D test_cases[i].json_out ?: test_cases[i].json_in; =20 - obj =3D qobject_from_json(json_in); + obj =3D qobject_from_json(json_in, NULL); if (utf8_out) { str =3D qobject_to_qstring(obj); g_assert(str); @@ -836,7 +836,7 @@ static void utf8_string(void) * FIXME Enable once these bugs have been fixed. */ if (0 && json_out !=3D json_in) { - obj =3D qobject_from_json(json_out); + obj =3D qobject_from_json(json_out, NULL); str =3D qobject_to_qstring(obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, utf8_out); @@ -886,7 +886,7 @@ static void simple_number(void) for (i =3D 0; test_cases[i].encoded; i++) { QInt *qint; =20 - qint =3D qobject_to_qint(qobject_from_json(test_cases[i].encoded)); + qint =3D qobject_to_qint(qobject_from_json(test_cases[i].encoded, = NULL)); g_assert(qint); g_assert(qint_get_int(qint) =3D=3D test_cases[i].decoded); if (test_cases[i].skip =3D=3D 0) { @@ -920,7 +920,7 @@ static void float_number(void) QObject *obj; QFloat *qfloat; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); qfloat =3D qobject_to_qfloat(obj); g_assert(qfloat); g_assert(qfloat_get_double(qfloat) =3D=3D test_cases[i].decoded); @@ -965,7 +965,7 @@ static void keyword_literal(void) QObject *null; QString *str; =20 - obj =3D qobject_from_json("true"); + obj =3D qobject_from_json("true", NULL); qbool =3D qobject_to_qbool(obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); @@ -976,7 +976,7 @@ static void keyword_literal(void) =20 QDECREF(qbool); =20 - obj =3D qobject_from_json("false"); + obj =3D qobject_from_json("false", NULL); qbool =3D qobject_to_qbool(obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D false); @@ -998,7 +998,7 @@ static void keyword_literal(void) g_assert(qbool_get_bool(qbool) =3D=3D true); QDECREF(qbool); =20 - obj =3D qobject_from_json("null"); + obj =3D qobject_from_json("null", NULL); g_assert(obj !=3D NULL); g_assert(qobject_type(obj) =3D=3D QTYPE_QNULL); =20 @@ -1134,13 +1134,13 @@ static void simple_dict(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str)); + obj =3D qobject_from_json(qstring_get_str(str), NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); qobject_decref(obj); QDECREF(str); @@ -1192,7 +1192,7 @@ static void large_dict(void) QObject *obj; =20 gen_test_json(gstr, 10, 100); - obj =3D qobject_from_json(gstr->str); + obj =3D qobject_from_json(gstr->str, NULL); g_assert(obj !=3D NULL); =20 qobject_decref(obj); @@ -1243,13 +1243,13 @@ static void simple_list(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str)); + obj =3D qobject_from_json(qstring_get_str(str), NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); qobject_decref(obj); QDECREF(str); @@ -1305,13 +1305,13 @@ static void simple_whitespace(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded); + obj =3D qobject_from_json(test_cases[i].encoded, NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str)); + obj =3D qobject_from_json(qstring_get_str(str), NULL); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 qobject_decref(obj); @@ -1332,7 +1332,7 @@ static void simple_varargs(void) {}})), {}})); =20 - embedded_obj =3D qobject_from_json("[32, 42]"); + embedded_obj =3D qobject_from_json("[32, 42]", NULL); g_assert(embedded_obj !=3D NULL); =20 obj =3D qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj); @@ -1345,67 +1345,67 @@ static void empty_input(void) { const char *empty =3D ""; =20 - QObject *obj =3D qobject_from_json(empty); + QObject *obj =3D qobject_from_json(empty, NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_string(void) { - QObject *obj =3D qobject_from_json("\"abc"); + QObject *obj =3D qobject_from_json("\"abc", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_sq_string(void) { - QObject *obj =3D qobject_from_json("'abc"); + QObject *obj =3D qobject_from_json("'abc", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_escape(void) { - QObject *obj =3D qobject_from_json("\"abc\\\""); + QObject *obj =3D qobject_from_json("\"abc\\\"", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_array(void) { - QObject *obj =3D qobject_from_json("[32"); + QObject *obj =3D qobject_from_json("[32", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_array_comma(void) { - QObject *obj =3D qobject_from_json("[32,"); + QObject *obj =3D qobject_from_json("[32,", NULL); g_assert(obj =3D=3D NULL); } =20 static void invalid_array_comma(void) { - QObject *obj =3D qobject_from_json("[32,}"); + QObject *obj =3D qobject_from_json("[32,}", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_dict(void) { - QObject *obj =3D qobject_from_json("{'abc':32"); + QObject *obj =3D qobject_from_json("{'abc':32", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_dict_comma(void) { - QObject *obj =3D qobject_from_json("{'abc':32,"); + QObject *obj =3D qobject_from_json("{'abc':32,", NULL); g_assert(obj =3D=3D NULL); } =20 static void invalid_dict_comma(void) { - QObject *obj =3D qobject_from_json("{'abc':32,}"); + QObject *obj =3D qobject_from_json("{'abc':32,}", NULL); g_assert(obj =3D=3D NULL); } =20 static void unterminated_literal(void) { - QObject *obj =3D qobject_from_json("nul"); + QObject *obj =3D qobject_from_json("nul", NULL); g_assert(obj =3D=3D NULL); } =20 @@ -1425,11 +1425,11 @@ static void limits_nesting(void) char buf[2 * (max_nesting + 1) + 1]; QObject *obj; =20 - obj =3D qobject_from_json(make_nest(buf, max_nesting)); + obj =3D qobject_from_json(make_nest(buf, max_nesting), NULL); g_assert(obj !=3D NULL); qobject_decref(obj); =20 - obj =3D qobject_from_json(make_nest(buf, max_nesting + 1)); + obj =3D qobject_from_json(make_nest(buf, max_nesting + 1), NULL); g_assert(obj =3D=3D NULL); } =20 diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serial= ization.c index c7e64f0..37dff41 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -1037,7 +1037,7 @@ static void qmp_deserialize(void **native_out, void *= datap, visit_complete(d->qov, &d->obj); obj_orig =3D d->obj; output_json =3D qobject_to_json(obj_orig); - obj =3D qobject_from_json(qstring_get_str(output_json)); + obj =3D qobject_from_json(qstring_get_str(output_json), NULL); =20 QDECREF(output_json); d->qiv =3D qobject_input_visitor_new(obj); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321329832978.8433081654483; Tue, 28 Feb 2017 14:35:29 -0800 (PST) Received: from localhost ([::1]:37421 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqMi-00041G-Jq for importer@patchew.org; Tue, 28 Feb 2017 17:35:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33662) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDv-00057z-I5 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000YW-F9 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38634) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xh-9J for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 7CA988047E for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQJsQ029012 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D25F81138607; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:04 +0100 Message-Id: <1488320775-9849-14-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.28]); Tue, 28 Feb 2017 22:26: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] [PULL 13/24] block: More detailed syntax error reporting for JSON filenames 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: Kevin Wolf Message-Id: <1488317230-26248-14-git-send-email-armbru@redhat.com> --- block.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index af1014f..ca15e93 100644 --- a/block.c +++ b/block.c @@ -1200,9 +1200,14 @@ static QDict *parse_json_filename(const char *filena= me, Error **errp) ret =3D strstart(filename, "json:", &filename); assert(ret); =20 - options_obj =3D qobject_from_json(filename, NULL); + options_obj =3D qobject_from_json(filename, errp); if (!options_obj) { - error_setg(errp, "Could not parse the JSON options"); + /* Work around qobject_from_json() lossage TODO fix that */ + if (errp && !*errp) { + error_setg(errp, "Could not parse the JSON options"); + return NULL; + } + error_prepend(errp, "Could not parse the JSON options: "); return NULL; } =20 --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488320990408884.6109275415741; Tue, 28 Feb 2017 14:29:50 -0800 (PST) Received: from localhost ([::1]:37393 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqHF-0007Kj-0O for importer@patchew.org; Tue, 28 Feb 2017 17:29:49 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33728) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDx-00059N-5T for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDs-0000ZA-Pg for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56648) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDs-0000Xl-G3 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:20 -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 AD2D7C04B320 for ; Tue, 28 Feb 2017 22:26:20 +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 v1SMQJMd029014 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:20 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D54E7113860A; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:05 +0100 Message-Id: <1488320775-9849-15-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.31]); Tue, 28 Feb 2017 22:26: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] [PULL 14/24] check-qjson: Test errors from qobject_from_json() 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" Pass &error_abort with known-good input. Else pass &err and check what comes back. This demonstrates that the parser fails silently for many errors. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-15-git-send-email-armbru@redhat.com> --- tests/check-qjson.c | 88 ++++++++++++++++++++++++++++++++++---------------= ---- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/tests/check-qjson.c b/tests/check-qjson.c index aa63758..963dd46 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -10,8 +10,10 @@ * See the COPYING.LIB file in the top-level directory. * */ + #include "qemu/osdep.h" =20 +#include "qapi/error.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qjson.h" #include "qemu-common.h" @@ -53,7 +55,7 @@ static void escaped_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); str =3D qobject_to_qstring(obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, test_cases[i].decode= d); @@ -85,7 +87,7 @@ static void simple_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); str =3D qobject_to_qstring(obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -116,7 +118,7 @@ static void single_quote_string(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); str =3D qobject_to_qstring(obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -809,7 +811,7 @@ static void utf8_string(void) utf8_in =3D test_cases[i].utf8_in ?: test_cases[i].utf8_out; json_out =3D test_cases[i].json_out ?: test_cases[i].json_in; =20 - obj =3D qobject_from_json(json_in, NULL); + obj =3D qobject_from_json(json_in, utf8_out ? &error_abort : NULL); if (utf8_out) { str =3D qobject_to_qstring(obj); g_assert(str); @@ -836,7 +838,7 @@ static void utf8_string(void) * FIXME Enable once these bugs have been fixed. */ if (0 && json_out !=3D json_in) { - obj =3D qobject_from_json(json_out, NULL); + obj =3D qobject_from_json(json_out, &error_abort); str =3D qobject_to_qstring(obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, utf8_out); @@ -886,7 +888,8 @@ static void simple_number(void) for (i =3D 0; test_cases[i].encoded; i++) { QInt *qint; =20 - qint =3D qobject_to_qint(qobject_from_json(test_cases[i].encoded, = NULL)); + qint =3D qobject_to_qint(qobject_from_json(test_cases[i].encoded, + &error_abort)); g_assert(qint); g_assert(qint_get_int(qint) =3D=3D test_cases[i].decoded); if (test_cases[i].skip =3D=3D 0) { @@ -920,7 +923,7 @@ static void float_number(void) QObject *obj; QFloat *qfloat; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); qfloat =3D qobject_to_qfloat(obj); g_assert(qfloat); g_assert(qfloat_get_double(qfloat) =3D=3D test_cases[i].decoded); @@ -965,7 +968,7 @@ static void keyword_literal(void) QObject *null; QString *str; =20 - obj =3D qobject_from_json("true", NULL); + obj =3D qobject_from_json("true", &error_abort); qbool =3D qobject_to_qbool(obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); @@ -976,7 +979,7 @@ static void keyword_literal(void) =20 QDECREF(qbool); =20 - obj =3D qobject_from_json("false", NULL); + obj =3D qobject_from_json("false", &error_abort); qbool =3D qobject_to_qbool(obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D false); @@ -998,7 +1001,7 @@ static void keyword_literal(void) g_assert(qbool_get_bool(qbool) =3D=3D true); QDECREF(qbool); =20 - obj =3D qobject_from_json("null", NULL); + obj =3D qobject_from_json("null", &error_abort); g_assert(obj !=3D NULL); g_assert(qobject_type(obj) =3D=3D QTYPE_QNULL); =20 @@ -1134,13 +1137,13 @@ static void simple_dict(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str), NULL); + obj =3D qobject_from_json(qstring_get_str(str), &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); qobject_decref(obj); QDECREF(str); @@ -1192,7 +1195,7 @@ static void large_dict(void) QObject *obj; =20 gen_test_json(gstr, 10, 100); - obj =3D qobject_from_json(gstr->str, NULL); + obj =3D qobject_from_json(gstr->str, &error_abort); g_assert(obj !=3D NULL); =20 qobject_decref(obj); @@ -1243,13 +1246,13 @@ static void simple_list(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str), NULL); + obj =3D qobject_from_json(qstring_get_str(str), &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); qobject_decref(obj); QDECREF(str); @@ -1305,13 +1308,13 @@ static void simple_whitespace(void) QObject *obj; QString *str; =20 - obj =3D qobject_from_json(test_cases[i].encoded, NULL); + obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 str =3D qobject_to_json(obj); qobject_decref(obj); =20 - obj =3D qobject_from_json(qstring_get_str(str), NULL); + obj =3D qobject_from_json(qstring_get_str(str), &error_abort); g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) =3D= =3D 1); =20 qobject_decref(obj); @@ -1332,7 +1335,7 @@ static void simple_varargs(void) {}})), {}})); =20 - embedded_obj =3D qobject_from_json("[32, 42]", NULL); + embedded_obj =3D qobject_from_json("[32, 42]", &error_abort); g_assert(embedded_obj !=3D NULL); =20 obj =3D qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj); @@ -1344,68 +1347,87 @@ static void simple_varargs(void) static void empty_input(void) { const char *empty =3D ""; - - QObject *obj =3D qobject_from_json(empty, NULL); + QObject *obj =3D qobject_from_json(empty, &error_abort); g_assert(obj =3D=3D NULL); } =20 static void unterminated_string(void) { - QObject *obj =3D qobject_from_json("\"abc", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("\"abc", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void unterminated_sq_string(void) { - QObject *obj =3D qobject_from_json("'abc", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("'abc", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void unterminated_escape(void) { - QObject *obj =3D qobject_from_json("\"abc\\\"", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("\"abc\\\"", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void unterminated_array(void) { - QObject *obj =3D qobject_from_json("[32", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("[32", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void unterminated_array_comma(void) { - QObject *obj =3D qobject_from_json("[32,", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("[32,", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void invalid_array_comma(void) { - QObject *obj =3D qobject_from_json("[32,}", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("[32,}", &err); + error_free_or_abort(&err); g_assert(obj =3D=3D NULL); } =20 static void unterminated_dict(void) { - QObject *obj =3D qobject_from_json("{'abc':32", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("{'abc':32", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void unterminated_dict_comma(void) { - QObject *obj =3D qobject_from_json("{'abc':32,", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("{'abc':32,", &err); + g_assert(!err); /* BUG */ g_assert(obj =3D=3D NULL); } =20 static void invalid_dict_comma(void) { - QObject *obj =3D qobject_from_json("{'abc':32,}", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("{'abc':32,}", &err); + error_free_or_abort(&err); g_assert(obj =3D=3D NULL); } =20 static void unterminated_literal(void) { - QObject *obj =3D qobject_from_json("nul", NULL); + Error *err =3D NULL; + QObject *obj =3D qobject_from_json("nul", &err); + error_free_or_abort(&err); g_assert(obj =3D=3D NULL); } =20 @@ -1421,15 +1443,17 @@ static char *make_nest(char *buf, size_t cnt) =20 static void limits_nesting(void) { + Error *err =3D NULL; enum { max_nesting =3D 1024 }; /* see qobject/json-streamer.c */ char buf[2 * (max_nesting + 1) + 1]; QObject *obj; =20 - obj =3D qobject_from_json(make_nest(buf, max_nesting), NULL); + obj =3D qobject_from_json(make_nest(buf, max_nesting), &error_abort); g_assert(obj !=3D NULL); qobject_decref(obj); =20 - obj =3D qobject_from_json(make_nest(buf, max_nesting + 1), NULL); + obj =3D qobject_from_json(make_nest(buf, max_nesting + 1), &err); + error_free_or_abort(&err); g_assert(obj =3D=3D NULL); } =20 --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321270861933.2183036465375; Tue, 28 Feb 2017 14:34:30 -0800 (PST) Received: from localhost ([::1]:37417 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqLl-0003JI-CJ for importer@patchew.org; Tue, 28 Feb 2017 17:34:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33707) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDw-00058y-No for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000be-4K for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48628) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000Zl-Lg for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -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 D493F64A5A for ; Tue, 28 Feb 2017 22:26:21 +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 v1SMQKik017908 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D81E5113860D; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:06 +0100 Message-Id: <1488320775-9849-16-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.26]); Tue, 28 Feb 2017 22:26: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] [PULL 15/24] test-visitor-serialization: Pass &error_abort to qobject_from_json() 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_deserialize() calls qobject_from_json() ignoring errors. It passes the result to qobject_input_visitor_new(), which asserts it's not null. Therefore, we can just as well pass &error_abort to qobject_from_json(). Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-16-git-send-email-armbru@redhat.com> --- tests/test-visitor-serialization.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serial= ization.c index 37dff41..4d47cee 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -1037,7 +1037,7 @@ static void qmp_deserialize(void **native_out, void *= datap, visit_complete(d->qov, &d->obj); obj_orig =3D d->obj; output_json =3D qobject_to_json(obj_orig); - obj =3D qobject_from_json(qstring_get_str(output_json), NULL); + obj =3D qobject_from_json(qstring_get_str(output_json), &error_abort); =20 QDECREF(output_json); d->qiv =3D qobject_input_visitor_new(obj); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321457854140.53477671038036; Tue, 28 Feb 2017 14:37:37 -0800 (PST) Received: from localhost ([::1]:37436 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqOm-0005Yy-I2 for importer@patchew.org; Tue, 28 Feb 2017 17:37:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDv-00058G-QV for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000bE-3n for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54590) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000Zi-L5 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -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 D0FFC7FB67 for ; Tue, 28 Feb 2017 22:26:21 +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 9BA511DCC0 for ; Tue, 28 Feb 2017 22:26:21 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DAEDD1138610; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:07 +0100 Message-Id: <1488320775-9849-17-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.25]); Tue, 28 Feb 2017 22:26: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] [PULL 16/24] monitor: Assert qmp_schema_json[] is sane 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_query_qmp_schema() parses qmp_schema_json[] with qobject_from_json(). This must not fail, so pass &error_abort. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-17-git-send-email-armbru@redhat.com> --- monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index 858bcda..13f6133 100644 --- a/monitor.c +++ b/monitor.c @@ -950,7 +950,7 @@ EventInfoList *qmp_query_events(Error **errp) static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, Error **errp) { - *ret_data =3D qobject_from_json(qmp_schema_json, NULL); + *ret_data =3D qobject_from_json(qmp_schema_json, &error_abort); } =20 /* --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321397160811.3826604823976; Tue, 28 Feb 2017 14:36:37 -0800 (PST) Received: from localhost ([::1]:37431 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqNo-0004oO-07 for importer@patchew.org; Tue, 28 Feb 2017 17:36:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33817) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDy-0005B2-QQ for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000c7-7i for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54592) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000Zq-NN for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 D835E7FB68 for ; Tue, 28 Feb 2017 22:26: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 v1SMQKKC011105 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DDE131138613; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:08 +0100 Message-Id: <1488320775-9849-18-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.25]); Tue, 28 Feb 2017 22:26: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] [PULL 17/24] test-qapi-util: New, covering qapi/qapi-util.c 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: Kevin Wolf Message-Id: <1488317230-26248-18-git-send-email-armbru@redhat.com> --- tests/.gitignore | 1 + tests/Makefile.include | 3 +++ tests/test-qapi-util.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 55 insertions(+) create mode 100644 tests/test-qapi-util.c diff --git a/tests/.gitignore b/tests/.gitignore index 30b7740..a966740 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -53,6 +53,7 @@ test-mul64 test-opts-visitor test-qapi-event.[ch] test-qapi-types.[ch] +test-qapi-util test-qapi-visit.[ch] test-qdev-global-props test-qemu-opts diff --git a/tests/Makefile.include b/tests/Makefile.include index e3b4f27..4b09fcd 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -128,6 +128,8 @@ gcov-files-check-bufferiszero-y =3D util/bufferiszero.c check-unit-y +=3D tests/test-uuid$(EXESUF) check-unit-y +=3D tests/ptimer-test$(EXESUF) gcov-files-ptimer-test-y =3D hw/core/ptimer.c +check-unit-y +=3D tests/test-qapi-util$(EXESUF) +gcov-files-test-qapi-util-y =3D qapi/qapi-util.c =20 check-block-$(CONFIG_POSIX) +=3D tests/qemu-iotests-quick.sh =20 @@ -732,6 +734,7 @@ tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contr= ib/ivshmem-server/ivshmem tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o contrib/libvho= st-user/libvhost-user.o $(test-util-obj-y) tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y) tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o +tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) =20 tests/migration/stress$(EXESUF): tests/migration/stress.o $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"L= INK","$(TARGET_DIR)$@") diff --git a/tests/test-qapi-util.c b/tests/test-qapi-util.c new file mode 100644 index 0000000..39db8bf --- /dev/null +++ b/tests/test-qapi-util.c @@ -0,0 +1,51 @@ +/* + * Unit tests for QAPI utility functions + * + * 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 "qapi/error.h" +#include "qapi/util.h" +#include "test-qapi-types.h" + +static void test_qapi_enum_parse(void) +{ + Error *err =3D NULL; + int ret; + + ret =3D qapi_enum_parse(QType_lookup, NULL, QTYPE__MAX, QTYPE_NONE, + &error_abort); + g_assert_cmpint(ret, =3D=3D, QTYPE_NONE); + + ret =3D qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1, + NULL); + g_assert_cmpint(ret, =3D=3D, -1); + + ret =3D qapi_enum_parse(QType_lookup, "junk", QTYPE__MAX, -1, + &err); + error_free_or_abort(&err); + + ret =3D qapi_enum_parse(QType_lookup, "none", QTYPE__MAX, -1, + &error_abort); + g_assert_cmpint(ret, =3D=3D, QTYPE_NONE); + + ret =3D qapi_enum_parse(QType_lookup, QType_lookup[QTYPE__MAX - 1], + QTYPE__MAX, QTYPE__MAX - 1, + &error_abort); + g_assert_cmpint(ret, =3D=3D, QTYPE__MAX - 1); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/qapi/util/qapi_enum_parse", test_qapi_enum_parse); + g_test_run(); + return 0; +} --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321869794146.40528836294936; Tue, 28 Feb 2017 14:44:29 -0800 (PST) Received: from localhost ([::1]:37473 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqVQ-00036p-7z for importer@patchew.org; Tue, 28 Feb 2017 17:44:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33824) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDy-0005BA-Tz for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000cO-7s for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38638) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000aA-Rn for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 0DA148047D for ; Tue, 28 Feb 2017 22:26: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 v1SMQKdR011108 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E0FEA1138616; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:09 +0100 Message-Id: <1488320775-9849-19-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.28]); Tue, 28 Feb 2017 22:26: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] [PULL 18/24] qapi: New parse_qapi_name() 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 Message-Id: <1488317230-26248-19-git-send-email-armbru@redhat.com> --- include/qapi/util.h | 2 ++ qapi/qapi-util.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test-qapi-util.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/include/qapi/util.h b/include/qapi/util.h index 7ad26c0..7436ed8 100644 --- a/include/qapi/util.h +++ b/include/qapi/util.h @@ -14,4 +14,6 @@ int qapi_enum_parse(const char * const lookup[], const char *buf, int max, int def, Error **errp); =20 +int parse_qapi_name(const char *name, bool complete); + #endif diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c index 818730a..e28dbd0 100644 --- a/qapi/qapi-util.c +++ b/qapi/qapi-util.c @@ -33,3 +33,50 @@ int qapi_enum_parse(const char * const lookup[], const c= har *buf, error_setg(errp, "invalid parameter value: %s", buf); return def; } + +/* + * Parse a valid QAPI name from @str. + * A valid name consists of letters, digits, hyphen and underscore. + * It may be prefixed by __RFQDN_ (downstream extension), where RFQDN + * may contain only letters, digits, hyphen and period. + * The special exception for enumeration names is not implemented. + * See docs/qapi-code-gen.txt for more on QAPI naming rules. + * Keep this consistent with scripts/qapi.py! + * If @complete, the parse fails unless it consumes @str completely. + * Return its length on success, -1 on failure. + */ +int parse_qapi_name(const char *str, bool complete) +{ + const char *p =3D str; + + if (*p =3D=3D '_') { /* Downstream __RFQDN_ */ + p++; + if (*p !=3D '_') { + return -1; + } + while (*++p) { + if (!qemu_isalnum(*p) && *p !=3D '-' && *p !=3D '.') { + break; + } + } + + if (*p !=3D '_') { + return -1; + } + p++; + } + + if (!qemu_isalpha(*p)) { + return -1; + } + while (*++p) { + if (!qemu_isalnum(*p) && *p !=3D '-' && *p !=3D '_') { + break; + } + } + + if (complete && *p) { + return -1; + } + return p - str; +} diff --git a/tests/test-qapi-util.c b/tests/test-qapi-util.c index 39db8bf..e869757 100644 --- a/tests/test-qapi-util.c +++ b/tests/test-qapi-util.c @@ -42,10 +42,44 @@ static void test_qapi_enum_parse(void) g_assert_cmpint(ret, =3D=3D, QTYPE__MAX - 1); } =20 +static void test_parse_qapi_name(void) +{ + int ret; + + /* Must start with a letter */ + ret =3D parse_qapi_name("a", true); + g_assert(ret =3D=3D 1); + ret =3D parse_qapi_name("a$", false); + g_assert(ret =3D=3D 1); + ret =3D parse_qapi_name("", false); + g_assert(ret =3D=3D -1); + ret =3D parse_qapi_name("1", false); + g_assert(ret =3D=3D -1); + + /* Only letters, digits, hyphen, underscore */ + ret =3D parse_qapi_name("A-Za-z0-9_", true); + g_assert(ret =3D=3D 10); + ret =3D parse_qapi_name("A-Za-z0-9_$", false); + g_assert(ret =3D=3D 10); + ret =3D parse_qapi_name("A-Za-z0-9_$", true); + g_assert(ret =3D=3D -1); + + /* __RFQDN_ */ + ret =3D parse_qapi_name("__com.redhat_supports", true); + g_assert(ret =3D=3D 21); + ret =3D parse_qapi_name("_com.example_", false); + g_assert(ret =3D=3D -1); + ret =3D parse_qapi_name("__com.example", false); + g_assert(ret =3D=3D -1); + ret =3D parse_qapi_name("__com.example_", false); + g_assert(ret =3D=3D -1); +} + int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func("/qapi/util/qapi_enum_parse", test_qapi_enum_parse); + g_test_add_func("/qapi/util/parse_qapi_name", test_parse_qapi_name); g_test_run(); return 0; } --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321571269358.9427913195241; Tue, 28 Feb 2017 14:39:31 -0800 (PST) Received: from localhost ([::1]:37453 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqQc-0007kJ-3y for importer@patchew.org; Tue, 28 Feb 2017 17:39:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33690) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDw-00058W-4a for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000bX-3Y for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51003) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000Zw-MJ for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -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 DD4FF3B731 for ; Tue, 28 Feb 2017 22:26:21 +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 v1SMQK6l026291 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E41751138619; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:10 +0100 Message-Id: <1488320775-9849-20-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.30]); Tue, 28 Feb 2017 22:26: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] [PULL 19/24] keyval: Restrict key components to valid QAPI names 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" Restricting the key components to something sane leaves us room for evolving key syntax. Since they will be commonly used as QAPI member names by the QObject input visitor, we can just as well borrow the QAPI naming rules here. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-20-git-send-email-armbru@redhat.com> --- tests/test-keyval.c | 10 ++++++++++ util/keyval.c | 12 ++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/test-keyval.c b/tests/test-keyval.c index 1c2aeea..efe27cd 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -41,6 +41,11 @@ static void test_keyval_parse(void) error_free_or_abort(&err); g_assert(!qdict); =20 + /* Invalid non-empty key (qemu_opts_parse() doesn't care) */ + qdict =3D keyval_parse("7up=3Dval", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + /* Overlong key */ memset(long_key, 'a', 127); long_key[127] =3D 'z'; @@ -73,6 +78,11 @@ static void test_keyval_parse(void) QDECREF(qdict); g_free(params); =20 + /* Crap after valid key */ + qdict =3D keyval_parse("key[0]=3Dval", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + /* Multiple keys, last one wins */ qdict =3D keyval_parse("a=3D1,b=3D2,,x,a=3D3", NULL, &error_abort); g_assert_cmpuint(qdict_size(qdict), =3D=3D, 2); diff --git a/util/keyval.c b/util/keyval.c index 990126f..29a6368 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -34,6 +34,8 @@ * doesn't have one, because R.a must be an object to satisfy a.b=3D1 * and a string to satisfy a=3D2. * + * Key-fragments must be valid QAPI names. + * * The length of any key-fragment must be between 1 and 127. * * Design flaw: there is no way to denote an empty non-root object. @@ -51,12 +53,12 @@ * where no-key is syntactic sugar for implied-key=3Dval-no-key. * * TODO support lists - * TODO support key-fragment with __RFQDN_ prefix (downstream extensions) */ =20 #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qmp/qstring.h" +#include "qapi/util.h" #include "qemu/option.h" =20 /* @@ -118,6 +120,7 @@ static const char *keyval_parse_one(QDict *qdict, const= char *params, size_t len; char key_in_cur[128]; QDict *cur; + int ret; QObject *next; QString *val; =20 @@ -137,9 +140,10 @@ static const char *keyval_parse_one(QDict *qdict, cons= t char *params, cur =3D qdict; s =3D key; for (;;) { - for (len =3D 0; s + len < key_end && s[len] !=3D '.'; len++) { - } - if (!len) { + ret =3D parse_qapi_name(s, false); + len =3D ret < 0 ? 0 : ret; + assert(s + len <=3D key_end); + if (!len || (s + len < key_end && s[len] !=3D '.')) { assert(key !=3D implied_key); error_setg(errp, "Invalid parameter '%.*s'", (int)(key_end - key), key); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321753039760.5781080733333; Tue, 28 Feb 2017 14:42:33 -0800 (PST) Received: from localhost ([::1]:37469 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqTX-0002BD-GD for importer@patchew.org; Tue, 28 Feb 2017 17:42:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33767) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDx-00059x-Vr for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000c0-6O for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38636) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000a6-NE for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 E1B7F8047B for ; Tue, 28 Feb 2017 22:26: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 v1SMQKI7029021 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E8467113861C; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:11 +0100 Message-Id: <1488320775-9849-21-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.28]); Tue, 28 Feb 2017 22:26: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] [PULL 20/24] qapi: New qobject_input_visitor_new_str() for convenience 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 Message-Id: <1488317230-26248-21-git-send-email-armbru@redhat.com> --- include/qapi/qobject-input-visitor.h | 12 ++++++++++++ qapi/qobject-input-visitor.c | 36 ++++++++++++++++++++++++++++++++= ++++ 2 files changed, 48 insertions(+) diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-in= put-visitor.h index 282f9d2..b399285 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -68,4 +68,16 @@ Visitor *qobject_input_visitor_new(QObject *obj); */ Visitor *qobject_input_visitor_new_keyval(QObject *obj); =20 +/* + * Create a QObject input visitor for parsing @str. + * + * If @str looks like JSON, parse it as JSON, else as KEY=3DVALUE,... + * @implied_key applies to KEY=3DVALUE, and works as in keyval_parse(). + * On failure, store an error through @errp and return NULL. + * On success, return a new QObject input visitor for the parse. + */ +Visitor *qobject_input_visitor_new_str(const char *str, + const char *implied_key, + Error **errp); + #endif diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 6c56040..1a484d5 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -18,9 +18,11 @@ #include "qapi/visitor-impl.h" #include "qemu/queue.h" #include "qemu-common.h" +#include "qapi/qmp/qjson.h" #include "qapi/qmp/types.h" #include "qapi/qmp/qerror.h" #include "qemu/cutils.h" +#include "qemu/option.h" =20 typedef struct StackObject { const char *name; /* Name of @obj in its parent, if any */ @@ -656,3 +658,37 @@ Visitor *qobject_input_visitor_new_keyval(QObject *obj) =20 return &v->visitor; } + +Visitor *qobject_input_visitor_new_str(const char *str, + const char *implied_key, + Error **errp) +{ + bool is_json =3D str[0] =3D=3D '{'; + QObject *obj; + QDict *args; + Visitor *v; + + if (is_json) { + obj =3D qobject_from_json(str, errp); + if (!obj) { + /* Work around qobject_from_json() lossage TODO fix that */ + if (errp && !*errp) { + error_setg(errp, "JSON parse error"); + return NULL; + } + return NULL; + } + args =3D qobject_to_qdict(obj); + assert(args); + v =3D qobject_input_visitor_new(QOBJECT(args)); + } else { + args =3D keyval_parse(str, implied_key, errp); + if (!args) { + return NULL; + } + v =3D qobject_input_visitor_new_keyval(QOBJECT(args)); + } + QDECREF(args); + + return v; +} --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488320855355450.18220441698963; Tue, 28 Feb 2017 14:27:35 -0800 (PST) Received: from localhost ([::1]:37379 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqF4-0005I5-3W for importer@patchew.org; Tue, 28 Feb 2017 17:27:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33796) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDy-0005Ab-IE for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000cH-7Y for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40824) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000aB-Rt for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 1006D80F8D for ; Tue, 28 Feb 2017 22:26: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 A51F91DCC2 for ; Tue, 28 Feb 2017 22:26:21 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id E9F49113861F; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:12 +0100 Message-Id: <1488320775-9849-22-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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]); Tue, 28 Feb 2017 22:26: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] [PULL 21/24] block: Initial implementation of -blockdev 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 new command line option -blockdev works like QMP command blockdev-add. The option argument may be given in JSON syntax, exactly as in QMP. Example usage: -blockdev '{"node-name": "foo", "driver": "raw", "file": {"driver": "fi= le", "filename": "foo.img"} }' The JSON argument doesn't exactly blend into the existing option syntax, so the traditional KEY=3DVALUE,... syntax is also supported, using dotted keys to do the nesting: -blockdev node-name=3Dfoo,driver=3Draw,file.driver=3Dfile,file.filename= =3Dfoo.img This does not yet support lists or downstream extensions, i.e. keys with __RFQDN_ prefix, but the next few patches will take care of that. Note that calling qmp_blockdev_add() (say via qmp_marshal_block_add()) right away would crash. We need to stash the configuration for later instead. This is crudely done, and bypasses QemuOpts, even though storing configuration is what QemuOpts is for. Need to revamp option infrastructure to support QAPI types like BlockdevOptions. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Markus Armbruster Message-Id: <1488317230-26248-22-git-send-email-armbru@redhat.com> --- qemu-options.hx | 7 +++++++ vl.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index c85f77d..f5202c9 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -532,6 +532,13 @@ Use @var{file} as CD-ROM image (you cannot use @option= {-hdc} and using @file{/dev/cdrom} as filename (@pxref{host_drives}). ETEXI =20 +DEF("blockdev", HAS_ARG, QEMU_OPTION_blockdev, + "-blockdev [driver=3D]driver[,node-name=3DN][,discard=3Dignore|unmap]\= n" + " [,cache.direct=3Don|off][,cache.no-flush=3Don|off]\n" + " [,read-only=3Don|off][,detect-zeroes=3Don|off|unmap]\n" + " [,driver specific parameters...]\n" + " configure a block backend\n", QEMU_ARCH_ALL) + DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=3Dfile][,if=3Dtype][,bus=3Dn][,unit=3Dm][,media=3Dd][,in= dex=3Di]\n" " [,cyls=3Dc,heads=3Dh,secs=3Ds[,trans=3Dt]][,snapshot=3Don|off]= \n" diff --git a/vl.c b/vl.c index c6020b9..68405c6 100644 --- a/vl.c +++ b/vl.c @@ -95,6 +95,9 @@ int main(int argc, char **argv) #include "migration/colo.h" #include "sysemu/kvm.h" #include "sysemu/hax.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi-visit.h" #include "qapi/qmp/qjson.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -2975,6 +2978,13 @@ int main(int argc, char **argv, char **envp) Error *main_loop_err =3D NULL; Error *err =3D NULL; bool list_data_dirs =3D false; + typedef struct BlockdevOptions_queue { + BlockdevOptions *bdo; + Location loc; + QSIMPLEQ_ENTRY(BlockdevOptions_queue) entry; + } BlockdevOptions_queue; + QSIMPLEQ_HEAD(, BlockdevOptions_queue) bdo_queue + =3D QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); =20 module_call_init(MODULE_INIT_TRACE); =20 @@ -3117,6 +3127,25 @@ int main(int argc, char **argv, char **envp) drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optar= g, HD_OPTS); break; + case QEMU_OPTION_blockdev: + { + Visitor *v; + BlockdevOptions_queue *bdo; + + v =3D qobject_input_visitor_new_str(optarg, "driver", = &err); + if (!v) { + error_report_err(err); + exit(1); + } + + bdo =3D g_new(BlockdevOptions_queue, 1); + visit_type_BlockdevOptions(v, NULL, &bdo->bdo, + &error_fatal); + visit_free(v); + loc_save(&bdo->loc); + QSIMPLEQ_INSERT_TAIL(&bdo_queue, bdo, entry); + break; + } case QEMU_OPTION_drive: if (drive_def(optarg) =3D=3D NULL) { exit(1); @@ -4450,6 +4479,16 @@ int main(int argc, char **argv, char **envp) } =20 /* open the virtual block devices */ + while (!QSIMPLEQ_EMPTY(&bdo_queue)) { + BlockdevOptions_queue *bdo =3D QSIMPLEQ_FIRST(&bdo_queue); + + QSIMPLEQ_REMOVE_HEAD(&bdo_queue, entry); + loc_push_restore(&bdo->loc); + qmp_blockdev_add(bdo->bdo, &error_fatal); + loc_pop(&bdo->loc); + qapi_free_BlockdevOptions(bdo->bdo); + g_free(bdo); + } if (snapshot || replay_mode !=3D REPLAY_MODE_NONE) { qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, NULL); --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321811068914.7827508234792; Tue, 28 Feb 2017 14:43:31 -0800 (PST) Received: from localhost ([::1]:37471 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqUT-0002dq-LU for importer@patchew.org; Tue, 28 Feb 2017 17:43:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33760) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDx-00059v-TH for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000bv-4o for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51000) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000Zr-Mo for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:21 -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 DA0BC3B71F for ; Tue, 28 Feb 2017 22:26:21 +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 A5A0F1DCC3 for ; Tue, 28 Feb 2017 22:26:21 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id ED3751138541; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:13 +0100 Message-Id: <1488320775-9849-23-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.30]); Tue, 28 Feb 2017 22:26: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] [PULL 22/24] qapi: Improve how keyval input visitor reports unexpected dicts 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" Incorrect option -blockdev node-name=3Dfoo,driver=3Dfile,filename=3Dfoo.img,aio.unmap=3D= on is rejected with "Invalid parameter type for 'aio', expected: string". To make sense of this, you almost have to translate it into the equivalent QMP command { "execute": "blockdev-add", "arguments": { "node-name": "foo", "driver= ": "file", "filename": "foo.img", "aio": { "unmap": true } } } Improve the error message to "Parameters 'aio.*' are unexpected". Take care not to confuse the case "unexpected nested parameters" (i.e. the object is a QDict or QList) with the case "non-string scalar parameter". The latter is a misuse of the visitor, and should perhaps be an assertion. Note that test-qobject-input-visitor exercises this misuse in test_visitor_in_int_keyval(), test_visitor_in_bool_keyval() and test_visitor_in_number_keyval(). Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Message-Id: <1488317230-26248-23-git-send-email-armbru@redhat.com> --- qapi/qobject-input-visitor.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 1a484d5..b9acd86 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -167,9 +167,18 @@ static const char *qobject_input_get_keyval(QObjectInp= utVisitor *qiv, =20 qstr =3D qobject_to_qstring(qobj); if (!qstr) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, - full_name(qiv, name), "string"); - return NULL; + switch (qobject_type(qobj)) { + case QTYPE_QDICT: + case QTYPE_QLIST: + error_setg(errp, "Parameters '%s.*' are unexpected", + full_name(qiv, name)); + return NULL; + default: + /* Non-string scalar (should this be an assertion?) */ + error_setg(errp, "Internal error: parameter %s invalid", + full_name(qiv, name)); + return NULL; + } } =20 return qstring_get_str(qstr); @@ -479,6 +488,15 @@ static void qobject_input_type_str(Visitor *v, const c= har *name, char **obj, *obj =3D g_strdup(qstring_get_str(qstr)); } =20 +static void qobject_input_type_str_keyval(Visitor *v, const char *name, + char **obj, Error **errp) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + const char *str =3D qobject_input_get_keyval(qiv, name, errp); + + *obj =3D g_strdup(str); +} + static void qobject_input_type_number(Visitor *v, const char *name, double= *obj, Error **errp) { @@ -650,7 +668,7 @@ Visitor *qobject_input_visitor_new_keyval(QObject *obj) v->visitor.type_int64 =3D qobject_input_type_int64_keyval; v->visitor.type_uint64 =3D qobject_input_type_uint64_keyval; v->visitor.type_bool =3D qobject_input_type_bool_keyval; - v->visitor.type_str =3D qobject_input_type_str; + v->visitor.type_str =3D qobject_input_type_str_keyval; v->visitor.type_number =3D qobject_input_type_number_keyval; v->visitor.type_any =3D qobject_input_type_any; v->visitor.type_null =3D qobject_input_type_null; --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321516560589.054330199264; Tue, 28 Feb 2017 14:38:36 -0800 (PST) Received: from localhost ([::1]:37443 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqPj-000769-8g for importer@patchew.org; Tue, 28 Feb 2017 17:38:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33823) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqDy-0005B9-U1 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000cD-74 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46878) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDt-0000aF-T5 for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26: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 1736715561 for ; Tue, 28 Feb 2017 22:26: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 v1SMQKq0017538 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F02A511384AC; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:14 +0100 Message-Id: <1488320775-9849-24-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.29]); Tue, 28 Feb 2017 22:26: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] [PULL 23/24] docs/qapi-code-gen.txt: Clarify naming rules 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: Kevin Wolf Message-Id: <1488317230-26248-24-git-send-email-armbru@redhat.com> --- docs/qapi-code-gen.txt | 61 ++++++++++++++++++++++++++++++++--------------= ---- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 6746c10..9514d93 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -216,33 +216,38 @@ single-dimension array of that type; multi-dimension = arrays are not directly supported (although an array of a complex struct that contains an array member is possible). =20 +All names must begin with a letter, and contain only ASCII letters, +digits, hyphen, and underscore. There are two exceptions: enum values +may start with a digit, and names that are downstream extensions (see +section Downstream extensions) start with underscore. + +Names beginning with 'q_' are reserved for the generator, which uses +them for munging QMP names that resemble C keywords or other +problematic strings. For example, a member named "default" in qapi +becomes "q_default" in the generated C code. + Types, commands, and events share a common namespace. Therefore, generally speaking, type definitions should always use CamelCase for -user-defined type names, while built-in types are lowercase. Type -definitions should not end in 'Kind', as this namespace is used for -creating implicit C enums for visiting union types, or in 'List', as -this namespace is used for creating array types. Command names, -and member names within a type, should be all lower case with words -separated by a hyphen. However, some existing older commands and -complex types use underscore; when extending such expressions, -consistency is preferred over blindly avoiding underscore. Event -names should be ALL_CAPS with words separated by underscore. Member -names cannot start with 'has-' or 'has_', as this is reserved for -tracking optional members. +user-defined type names, while built-in types are lowercase. + +Type names ending with 'Kind' or 'List' are reserved for the +generator, which uses them for implicit union enums and array types, +respectively. + +Command names, and member names within a type, should be all lower +case with words separated by a hyphen. However, some existing older +commands and complex types use underscore; when extending such +expressions, consistency is preferred over blindly avoiding +underscore. + +Event names should be ALL_CAPS with words separated by underscore. + +Member names starting with 'has-' or 'has_' are reserved for the +generator, which uses them for tracking optional members. =20 Any name (command, event, type, member, or enum value) beginning with "x-" is marked experimental, and may be withdrawn or changed -incompatibly in a future release. All names must begin with a letter, -and contain only ASCII letters, digits, dash, and underscore. There -are two exceptions: enum values may start with a digit, and any -extensions added by downstream vendors should start with a prefix -matching "__RFQDN_" (for the reverse-fully-qualified-domain-name of -the vendor), even if the rest of the name uses dash (example: -__com.redhat_drive-mirror). Names beginning with 'q_' are reserved -for the generator: QMP names that resemble C keywords or other -problematic strings will be munged in C to use this prefix. For -example, a member named "default" in qapi becomes "q_default" in the -generated C code. +incompatibly in a future release. =20 In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and @@ -643,6 +648,18 @@ any non-empty complex type (struct, union, or alternat= e), and a pointer to that QAPI type is passed as a single argument. =20 =20 +=3D=3D=3D Downstream extensions =3D=3D=3D + +QAPI schema names that are externally visible, say in the Client JSON +Protocol, need to be managed with care. Names starting with a +downstream prefix of the form __RFQDN_ are reserved for the downstream +who controls the valid, reverse fully qualified domain name RFQDN. +RFQDN may only contain ASCII letters, digits, hyphen and period. + +Example: Red Hat, Inc. controls redhat.com, and may therefore add a +downstream command __com.redhat_drive-mirror. + + =3D=3D Client JSON Protocol introspection =3D=3D =20 Clients of a Client JSON Protocol commonly need to figure out what --=20 2.7.4 From nobody Sun May 5 07:43:36 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 1488321929851997.1750013693044; Tue, 28 Feb 2017 14:45:29 -0800 (PST) Received: from localhost ([::1]:37478 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqWO-0003aE-Bm for importer@patchew.org; Tue, 28 Feb 2017 17:45:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33926) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciqE1-0005Dc-Ci for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciqDu-0000ch-Hk for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:29 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48636) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciqDu-0000aP-6u for qemu-devel@nongnu.org; Tue, 28 Feb 2017 17:26:22 -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 47B697E9E8 for ; Tue, 28 Feb 2017 22:26:22 +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 v1SMQKeN017910 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 28 Feb 2017 17:26:21 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id F32C311384AE; Tue, 28 Feb 2017 23:26:15 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 28 Feb 2017 23:26:15 +0100 Message-Id: <1488320775-9849-25-git-send-email-armbru@redhat.com> In-Reply-To: <1488320775-9849-1-git-send-email-armbru@redhat.com> References: <1488320775-9849-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.26]); Tue, 28 Feb 2017 22:26: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] [PULL 24/24] keyval: Support lists 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" Additionally permit non-negative integers as key components. A dictionary's keys must either be all integers or none. If all keys are integers, convert the dictionary to a list. The set of keys must be [0,N]. Examples: * list.1=3Dgoner,list.0=3Dnull,list.1=3Deins,list.2=3Dzwei is equivalent to JSON [ "null", "eins", "zwei" ] * a.b.c=3D1,a.b.0=3D2 is inconsistent: a.b.c clashes with a.b.0 * list.0=3Dnull,list.2=3Deins,list.2=3Dzwei has a hole: list.1 is missing Similar design flaw as for objects: there is no way to denote an empty list. While interpreting "key absent" as empty list seems natural (removing a list member from the input string works when there are multiple ones, so why not when there's just one), it doesn't work: "key absent" already means "optional list absent", which isn't the same as "empty list present". Update the keyval object visitor to use this a.0 syntax in error messages rather than the usual a[0]. Signed-off-by: Markus Armbruster Message-Id: <1488317230-26248-25-git-send-email-armbru@redhat.com> [Off-by-one fix squashed in, as per Kevin's review] Reviewed-by: Kevin Wolf --- qapi/qobject-input-visitor.c | 6 +- tests/test-keyval.c | 122 +++++++++++++++++++++++++++++ util/keyval.c | 183 +++++++++++++++++++++++++++++++++++++++= +--- 3 files changed, 298 insertions(+), 13 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index b9acd86..865e948 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -41,6 +41,7 @@ struct QObjectInputVisitor { =20 /* Root of visit at visitor creation. */ QObject *root; + bool keyval; /* Assume @root made with keyval_parse() */ =20 /* Stack of objects being visited (all entries will be either * QDict or QList). */ @@ -73,7 +74,9 @@ static const char *full_name_nth(QObjectInputVisitor *qiv= , const char *name, g_string_prepend(qiv->errname, name ?: ""); g_string_prepend_c(qiv->errname, '.'); } else { - snprintf(buf, sizeof(buf), "[%u]", so->index); + snprintf(buf, sizeof(buf), + qiv->keyval ? ".%u" : "[%u]", + so->index); g_string_prepend(qiv->errname, buf); } name =3D so->name; @@ -673,6 +676,7 @@ Visitor *qobject_input_visitor_new_keyval(QObject *obj) v->visitor.type_any =3D qobject_input_type_any; v->visitor.type_null =3D qobject_input_type_null; v->visitor.type_size =3D qobject_input_type_size_keyval; + v->keyval =3D true; =20 return &v->visitor; } diff --git a/tests/test-keyval.c b/tests/test-keyval.c index efe27cd..71288b0 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -12,6 +12,7 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qmp/qstring.h" #include "qapi/qobject-input-visitor.h" #include "qemu/cutils.h" #include "qemu/option.h" @@ -183,6 +184,72 @@ static void test_keyval_parse(void) g_assert(!qdict); } =20 +static void check_list012(QList *qlist) +{ + static const char *expected[] =3D { "null", "eins", "zwei" }; + int i; + QString *qstr; + + g_assert(qlist); + for (i =3D 0; i < ARRAY_SIZE(expected); i++) { + qstr =3D qobject_to_qstring(qlist_pop(qlist)); + g_assert(qstr); + g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, expected[i]); + QDECREF(qstr); + } + g_assert(qlist_empty(qlist)); +} + +static void test_keyval_parse_list(void) +{ + Error *err =3D NULL; + QDict *qdict, *sub_qdict; + + /* Root can't be a list */ + qdict =3D keyval_parse("0=3D1", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* List elements need not be in order */ + qdict =3D keyval_parse("list.0=3Dnull,list.2=3Dzwei,list.1=3Deins", + NULL, &error_abort); + g_assert_cmpint(qdict_size(qdict), =3D=3D, 1); + check_list012(qdict_get_qlist(qdict, "list")); + QDECREF(qdict); + + /* Multiple indexes, last one wins */ + qdict =3D keyval_parse("list.1=3Dgoner,list.0=3Dnull,list.1=3Deins,lis= t.2=3Dzwei", + NULL, &error_abort); + g_assert_cmpint(qdict_size(qdict), =3D=3D, 1); + check_list012(qdict_get_qlist(qdict, "list")); + QDECREF(qdict); + + /* List at deeper nesting */ + qdict =3D keyval_parse("a.list.1=3Deins,a.list.0=3Dnull,a.list.2=3Dzwe= i", + NULL, &error_abort); + g_assert_cmpint(qdict_size(qdict), =3D=3D, 1); + sub_qdict =3D qdict_get_qdict(qdict, "a"); + g_assert_cmpint(qdict_size(sub_qdict), =3D=3D, 1); + check_list012(qdict_get_qlist(sub_qdict, "list")); + QDECREF(qdict); + + /* Inconsistent dotted keys: both list and dictionary */ + qdict =3D keyval_parse("a.b.c=3D1,a.b.0=3D2", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + qdict =3D keyval_parse("a.0.c=3D1,a.b.c=3D2", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + + /* Missing list indexes */ + qdict =3D keyval_parse("list.2=3Dlonely", NULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); + qdict =3D keyval_parse("list.0=3Dnull,list.2=3Deins,list.02=3Dzwei", N= ULL, &err); + error_free_or_abort(&err); + g_assert(!qdict); +} + static void test_keyval_visit_bool(void) { Error *err =3D NULL; @@ -459,6 +526,59 @@ static void test_keyval_visit_dict(void) visit_free(v); } =20 +static void test_keyval_visit_list(void) +{ + Error *err =3D NULL; + Visitor *v; + QDict *qdict; + char *s; + + qdict =3D keyval_parse("a.0=3D,a.1=3DI,a.2.0=3DII", NULL, &error_abort= ); + /* TODO empty list */ + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_list(v, "a", NULL, 0, &error_abort); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, ""); + g_free(s); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, "I"); + g_free(s); + visit_start_list(v, NULL, NULL, 0, &error_abort); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, "II"); + g_free(s); + visit_check_list(v, &error_abort); + visit_end_list(v, NULL); + visit_check_list(v, &error_abort); + visit_end_list(v, NULL); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + qdict =3D keyval_parse("a.0=3D,b.0.0=3Dhead", NULL, &error_abort); + v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + QDECREF(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_list(v, "a", NULL, 0, &error_abort); + visit_check_list(v, &err); /* a[0] unexpected */ + error_free_or_abort(&err); + visit_end_list(v, NULL); + visit_start_list(v, "b", NULL, 0, &error_abort); + visit_start_list(v, NULL, NULL, 0, &error_abort); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, "head"); + g_free(s); + visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */ + error_free_or_abort(&err); + visit_end_list(v, NULL); + visit_end_list(v, NULL); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); +} + static void test_keyval_visit_optional(void) { Visitor *v; @@ -492,10 +612,12 @@ int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func("/keyval/keyval_parse", test_keyval_parse); + g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list); g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool); g_test_add_func("/keyval/visit/number", test_keyval_visit_number); g_test_add_func("/keyval/visit/size", test_keyval_visit_size); g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict); + g_test_add_func("/keyval/visit/list", test_keyval_visit_list); g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); g_test_run(); return 0; diff --git a/util/keyval.c b/util/keyval.c index 29a6368..c316aaa 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -21,10 +21,12 @@ * * Semantics defined by reduction to JSON: * - * key-vals defines a tree of objects rooted at R + * key-vals is a tree of objects and arrays rooted at object R * where for each key-val =3D key-fragment . ... =3D val in key-vals * R op key-fragment op ... =3D val' - * where (left-associative) op is member reference L.key-fragment + * where (left-associative) op is + * array subscript L[key-fragment] for numeric key-fragment + * member reference L.key-fragment otherwise * val' is val with ',,' replaced by ',' * and only R may be empty. * @@ -34,16 +36,16 @@ * doesn't have one, because R.a must be an object to satisfy a.b=3D1 * and a string to satisfy a=3D2. * - * Key-fragments must be valid QAPI names. + * Key-fragments must be valid QAPI names or consist only of digits. * * The length of any key-fragment must be between 1 and 127. * - * Design flaw: there is no way to denote an empty non-root object. - * While interpreting "key absent" as empty object seems natural + * Design flaw: there is no way to denote an empty array or non-root + * object. While interpreting "key absent" as empty seems natural * (removing a key-val from the input string removes the member when * there are more, so why not when it's the last), it doesn't work: - * "key absent" already means "optional object absent", which isn't - * the same as "empty object present". + * "key absent" already means "optional object/array absent", which + * isn't the same as "empty object/array present". * * Additional syntax for use with an implied key: * @@ -51,17 +53,43 @@ * val-no-key =3D / [^=3D,]* / * * where no-key is syntactic sugar for implied-key=3Dval-no-key. - * - * TODO support lists */ =20 #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qmp/qstring.h" #include "qapi/util.h" +#include "qemu/cutils.h" #include "qemu/option.h" =20 /* + * Convert @key to a list index. + * Convert all leading digits to a (non-negative) number, capped at + * INT_MAX. + * If @end is non-null, assign a pointer to the first character after + * the number to *@end. + * Else, fail if any characters follow. + * On success, return the converted number. + * On failure, return a negative value. + * Note: since only digits are converted, no two keys can map to the + * same number, except by overflow to INT_MAX. + */ +static int key_to_index(const char *key, const char **end) +{ + int ret; + unsigned long index; + + if (*key < '0' || *key > '9') { + return -EINVAL; + } + ret =3D qemu_strtoul(key, end, 10, &index); + if (ret) { + return ret =3D=3D -ERANGE ? INT_MAX : ret; + } + return index <=3D INT_MAX ? index : INT_MAX; +} + +/* * Ensure @cur maps @key_in_cur the right way. * If @value is null, it needs to map to a QDict, else to this * QString. @@ -116,7 +144,7 @@ static const char *keyval_parse_one(QDict *qdict, const= char *params, const char *implied_key, Error **errp) { - const char *key, *key_end, *s; + const char *key, *key_end, *s, *end; size_t len; char key_in_cur[128]; QDict *cur; @@ -140,8 +168,13 @@ static const char *keyval_parse_one(QDict *qdict, cons= t char *params, cur =3D qdict; s =3D key; for (;;) { - ret =3D parse_qapi_name(s, false); - len =3D ret < 0 ? 0 : ret; + /* Want a key index (unless it's first) or a QAPI name */ + if (s !=3D key && key_to_index(s, &end) >=3D 0) { + len =3D end - s; + } else { + ret =3D parse_qapi_name(s, false); + len =3D ret < 0 ? 0 : ret; + } assert(s + len <=3D key_end); if (!len || (s + len < key_end && s[len] !=3D '.')) { assert(key !=3D implied_key); @@ -208,6 +241,125 @@ static const char *keyval_parse_one(QDict *qdict, con= st char *params, return s; } =20 +static char *reassemble_key(GSList *key) +{ + GString *s =3D g_string_new(""); + GSList *p; + + for (p =3D key; p; p =3D p->next) { + g_string_prepend_c(s, '.'); + g_string_prepend(s, (char *)p->data); + } + + return g_string_free(s, FALSE); +} + +/* + * Listify @cur recursively. + * Replace QDicts whose keys are all valid list indexes by QLists. + * @key_of_cur is the list of key fragments leading up to @cur. + * On success, return either @cur or its replacement. + * On failure, store an error through @errp and return NULL. + */ +static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **err= p) +{ + GSList key_node; + bool has_index, has_member; + const QDictEntry *ent; + QDict *qdict; + QObject *val; + char *key; + size_t nelt; + QObject **elt; + int index, max_index, i; + QList *list; + + key_node.next =3D key_of_cur; + + /* + * Recursively listify @cur's members, and figure out whether @cur + * itself is to be listified. + */ + has_index =3D false; + has_member =3D false; + for (ent =3D qdict_first(cur); ent; ent =3D qdict_next(cur, ent)) { + if (key_to_index(ent->key, NULL) >=3D 0) { + has_index =3D true; + } else { + has_member =3D true; + } + + qdict =3D qobject_to_qdict(ent->value); + if (!qdict) { + continue; + } + + key_node.data =3D ent->key; + val =3D keyval_listify(qdict, &key_node, errp); + if (!val) { + return NULL; + } + if (val !=3D ent->value) { + qdict_put_obj(cur, ent->key, val); + } + } + + if (has_index && has_member) { + key =3D reassemble_key(key_of_cur); + error_setg(errp, "Parameters '%s*' used inconsistently", key); + g_free(key); + return NULL; + } + if (!has_index) { + return QOBJECT(cur); + } + + /* Copy @cur's values to @elt[] */ + nelt =3D qdict_size(cur) + 1; /* one extra, for use as sentinel */ + elt =3D g_new0(QObject *, nelt); + max_index =3D -1; + for (ent =3D qdict_first(cur); ent; ent =3D qdict_next(cur, ent)) { + index =3D key_to_index(ent->key, NULL); + assert(index >=3D 0); + if (index > max_index) { + max_index =3D index; + } + /* + * We iterate @nelt times. If we get one exceeding @nelt + * here, we will put less than @nelt values into @elt[], + * triggering the error in the next loop. + */ + if ((size_t)index >=3D nelt - 1) { + continue; + } + /* Even though dict keys are distinct, indexes need not be */ + elt[index] =3D ent->value; + } + + /* + * Make a list from @elt[], reporting any missing elements. + * If we dropped an index >=3D nelt in the previous loop, this loop + * will run into the sentinel and report index @nelt missing. + */ + list =3D qlist_new(); + assert(!elt[nelt-1]); /* need the sentinel to be null */ + for (i =3D 0; i < MIN(nelt, max_index + 1); i++) { + if (!elt[i]) { + key =3D reassemble_key(key_of_cur); + error_setg(errp, "Parameter '%s%d' missing", key, i); + g_free(key); + g_free(elt); + QDECREF(list); + return NULL; + } + qobject_incref(elt[i]); + qlist_append_obj(list, elt[i]); + } + + g_free(elt); + return QOBJECT(list); +} + /* * Parse @params in QEMU's traditional KEY=3DVALUE,... syntax. * If @implied_key, the first KEY=3D can be omitted. @implied_key is @@ -219,6 +371,7 @@ QDict *keyval_parse(const char *params, const char *imp= lied_key, Error **errp) { QDict *qdict =3D qdict_new(); + QObject *listified; const char *s; =20 s =3D params; @@ -231,5 +384,11 @@ QDict *keyval_parse(const char *params, const char *im= plied_key, implied_key =3D NULL; } =20 + listified =3D keyval_listify(qdict, NULL, errp); + if (!listified) { + QDECREF(qdict); + return NULL; + } + assert(listified =3D=3D QOBJECT(qdict)); return qdict; } --=20 2.7.4