From nobody Sat May 4 04:06:39 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 1488194631308277.092414757755; Mon, 27 Feb 2017 03:23:51 -0800 (PST) Received: from localhost ([::1]:51773 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJPB-0008ML-QT for importer@patchew.org; Mon, 27 Feb 2017 06:23:49 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44643) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00066Y-2z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMT-00011Z-TL for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48386) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMK-0000rS-Td; Mon, 27 Feb 2017 06:20:53 -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 0C6003A769B; Mon, 27 Feb 2017 11:20:53 +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 v1RBKp3r021110 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:52 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 0D8D2113864A; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:27 +0100 Message-Id: <1488194450-28056-2-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:53 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 01/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 1488194628797828.6129290559596; Mon, 27 Feb 2017 03:23:48 -0800 (PST) Received: from localhost ([::1]:51772 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJP9-0008KS-H6 for importer@patchew.org; Mon, 27 Feb 2017 06:23:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44570) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMU-000658-Uu for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-00010B-R2 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58611) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMK-0000rJ-P0; Mon, 27 Feb 2017 06:20:52 -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 E8D0F51451; Mon, 27 Feb 2017 11:20:52 +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 A72531DCC1; Mon, 27 Feb 2017 11:20:52 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 107EF113864D; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:28 +0100 Message-Id: <1488194450-28056-3-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 27 Feb 2017 11:20:52 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 02/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- tests/Makefile.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index cb97473..fdf528c 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 Sat May 4 04:06:39 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 148819594017336.85876702974667; Mon, 27 Feb 2017 03:45:40 -0800 (PST) Received: from localhost ([::1]:51897 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJkI-00032T-OH for importer@patchew.org; Mon, 27 Feb 2017 06:45:38 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44774) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DQ-4d for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMW-00014G-09 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48390) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJML-0000rW-8H; Mon, 27 Feb 2017 06:20:53 -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 733DB3A76AB; Mon, 27 Feb 2017 11:20:53 +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 A72EE1DCC2; Mon, 27 Feb 2017 11:20:52 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 1393F1138650; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:29 +0100 Message-Id: <1488194450-28056-4-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:53 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 03/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- include/qemu/option.h | 3 + tests/.gitignore | 1 + tests/Makefile.include | 3 + tests/test-keyval.c | 180 ++++++++++++++++++++++++++++++++++++++ util/Makefile.objs | 1 + util/keyval.c | 228 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 6 files changed, 416 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 fdf528c..2171e4a 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) @@ -721,6 +723,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..3904c39 --- /dev/null +++ b/util/keyval.c @@ -0,0 +1,228 @@ +/* + * 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-vals } ] + * 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 / [^,]* / + * + * 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. + * 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); + 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 Sat May 4 04:06:39 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 1488196214401988.4957067927716; Mon, 27 Feb 2017 03:50:14 -0800 (PST) Received: from localhost ([::1]:51934 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJoj-00075X-0Z for importer@patchew.org; Mon, 27 Feb 2017 06:50:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44775) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DR-5S for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMV-000147-Qu for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44986) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJML-0000rY-Ed; Mon, 27 Feb 2017 06:20:53 -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 9CF88804ED; Mon, 27 Feb 2017 11:20:53 +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 v1RBKp90009509 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:52 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 1829A1138657; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:30 +0100 Message-Id: <1488194450-28056-5-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.27]); Mon, 27 Feb 2017 11:20:53 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 04/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: , Cc: kwolf@redhat.com, pkrempa@redhat.com, qemu-block@nongnu.org, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com 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 --- 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 6bb5a80..d53bad3 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 */ @@ -336,6 +337,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) { @@ -357,6 +383,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) { @@ -377,6 +427,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) { @@ -425,6 +504,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) { @@ -455,6 +563,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); @@ -517,3 +649,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 8943cab..650637e 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); @@ -1068,10 +1226,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 Sat May 4 04:06:39 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 148819542231163.382131321233146; Mon, 27 Feb 2017 03:37:02 -0800 (PST) Received: from localhost ([::1]:51851 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJbw-0003Q4-Vn for importer@patchew.org; Mon, 27 Feb 2017 06:37:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44719) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMY-00068w-1h for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMU-00012f-L7 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:33284) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000te-LN; Mon, 27 Feb 2017 06:20:54 -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 D39F04E33E; Mon, 27 Feb 2017 11:20:54 +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 v1RBKrg4030331 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 1E20D11386CE; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:31 +0100 Message-Id: <1488194450-28056-6-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.38]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 05/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- tests/test-keyval.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 312 insertions(+) diff --git a/tests/test-keyval.c b/tests/test-keyval.c index 27f6625..f6496d7 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^54 */ + 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 Sat May 4 04:06:39 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 1488195921690219.89643476284857; Mon, 27 Feb 2017 03:45:21 -0800 (PST) Received: from localhost ([::1]:51895 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJk0-0002mB-Es for importer@patchew.org; Mon, 27 Feb 2017 06:45:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44752) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMZ-0006BM-N3 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-0000zw-NY for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:07 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51312) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000tk-MW; Mon, 27 Feb 2017 06:20:54 -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 D83D7C05B1C4; Mon, 27 Feb 2017 11:20:54 +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 v1RBKrHD021116 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 215C011386DC; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:32 +0100 Message-Id: <1488194450-28056-7-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 06/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 d53bad3..e47615e 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -618,22 +618,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; @@ -641,30 +653,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; @@ -673,11 +669,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 Sat May 4 04:06:39 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 1488194880455991.9194081615532; Mon, 27 Feb 2017 03:28:00 -0800 (PST) Received: from localhost ([::1]:51799 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJTD-0003sp-43 for importer@patchew.org; Mon, 27 Feb 2017 06:27:59 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44641) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00066W-2D for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMT-00010e-67 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49318) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000tT-KT; Mon, 27 Feb 2017 06:20:54 -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 CC8DE6AAD0; Mon, 27 Feb 2017 11:20:54 +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 v1RBKrj9021118 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2448D11385E0; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:33 +0100 Message-Id: <1488194450-28056-8-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.26]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 07/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/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 e47615e..3db5850 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; @@ -342,20 +364,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"); @@ -387,20 +402,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"); @@ -431,21 +439,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")) { @@ -508,22 +507,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) { @@ -567,20 +557,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 Sat May 4 04:06:39 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 1488194887720211.05819457779273; Mon, 27 Feb 2017 03:28:07 -0800 (PST) Received: from localhost ([::1]:51800 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJTK-00041U-Ea for importer@patchew.org; Mon, 27 Feb 2017 06:28:06 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44729) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMY-00069P-E9 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMT-00010L-2P for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57622) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000td-Ka; Mon, 27 Feb 2017 06:20:54 -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 D1CAD7FB70; Mon, 27 Feb 2017 11:20:54 +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 v1RBKrkP021120 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 270F611385E1; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:34 +0100 Message-Id: <1488194450-28056-9-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 08/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 650637e..44885ee 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 Sat May 4 04:06:39 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 1488195688800489.1607857765638; Mon, 27 Feb 2017 03:41:28 -0800 (PST) Received: from localhost ([::1]:51877 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJgD-0007U7-Gt for importer@patchew.org; Mon, 27 Feb 2017 06:41:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44636) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00066V-1p for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMT-00011K-Pr for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52426) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000tb-MO; Mon, 27 Feb 2017 06:20:54 -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 D33EF3D953; Mon, 27 Feb 2017 11:20:54 +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 v1RBKr5b019460 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2A01111385ED; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:35 +0100 Message-Id: <1488194450-28056-10-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.30]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 09/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 1488194613356961.8952864443743; Mon, 27 Feb 2017 03:23:33 -0800 (PST) Received: from localhost ([::1]:51770 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJOt-00083d-KC for importer@patchew.org; Mon, 27 Feb 2017 06:23:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44540) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMU-00063q-5c for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-0000zk-8b for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:33282) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000tX-Kg; Mon, 27 Feb 2017 06:20:54 -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 CFEA34E33D; Mon, 27 Feb 2017 11:20:54 +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 v1RBKr5o009522 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2D28611385F0; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:36 +0100 Message-Id: <1488194450-28056-11-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 27 Feb 2017 11:20:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 10/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 1488194593543399.6602201603255; Mon, 27 Feb 2017 03:23:13 -0800 (PST) Received: from localhost ([::1]:51769 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJOa-0007dX-8S for importer@patchew.org; Mon, 27 Feb 2017 06:23:12 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44566) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMU-00064s-O6 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-000100-O5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:43415) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMM-0000u0-Rs; Mon, 27 Feb 2017 06:20:55 -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 0F08951451; Mon, 27 Feb 2017 11:20:55 +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 CA0FF2D655; Mon, 27 Feb 2017 11:20:54 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 3005411385FC; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:37 +0100 Message-Id: <1488194450-28056-12-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 27 Feb 2017 11:20:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 11/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 44885ee..746dfa3 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 Sat May 4 04:06:39 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 1488195144927631.5423621130948; Mon, 27 Feb 2017 03:32:24 -0800 (PST) Received: from localhost ([::1]:51824 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJXS-0007nG-Gg for importer@patchew.org; Mon, 27 Feb 2017 06:32:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44730) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMY-00069S-Ef for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMU-00012n-PE for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51316) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMN-0000u7-8v; Mon, 27 Feb 2017 06:20:55 -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 6E513C054C3C; Mon, 27 Feb 2017 11:20:55 +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 v1RBKrHr003140 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 32F651138604; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:38 +0100 Message-Id: <1488194450-28056-13-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.32]); Mon, 27 Feb 2017 11:20:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 12/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- block.c | 2 +- include/qapi/qmp/qjson.h | 5 +-- monitor.c | 2 +- qobject/qjson.c | 4 +-- tests/check-qjson.c | 62 +++++++++++++++++++---------------= ---- tests/test-visitor-serialization.c | 2 +- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/block.c b/block.c index 3c36af5..aa6790c 100644 --- a/block.c +++ b/block.c @@ -1163,7 +1163,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..8568f2d 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -17,8 +17,9 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" =20 -QObject *qobject_from_json(const char *string); -QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); +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); =20 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 Sat May 4 04:06:39 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 1488195422316345.44144840176807; Mon, 27 Feb 2017 03:37:02 -0800 (PST) Received: from localhost ([::1]:51852 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJbx-0003QK-2m for importer@patchew.org; Mon, 27 Feb 2017 06:37:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44578) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMV-00065O-2C for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-0000za-3z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49324) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMN-0000u5-3q; Mon, 27 Feb 2017 06:20:55 -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 495527E9E2; Mon, 27 Feb 2017 11:20:55 +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 v1RBKrtB009530 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:54 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 35FA41138607; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:39 +0100 Message-Id: <1488194450-28056-14-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 27 Feb 2017 11:20:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 13/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- block.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index aa6790c..de7d530 100644 --- a/block.c +++ b/block.c @@ -1163,9 +1163,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 Sat May 4 04:06:39 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 14881951268611011.1031557592752; Mon, 27 Feb 2017 03:32:06 -0800 (PST) Received: from localhost ([::1]:51823 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJXB-0007bQ-Cp for importer@patchew.org; Mon, 27 Feb 2017 06:32:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44661) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00067i-NX for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMU-00012F-8m for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45000) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMN-0000u3-28; Mon, 27 Feb 2017 06:20:55 -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 471A880F96; Mon, 27 Feb 2017 11:20:55 +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 D759C1DCC0; Mon, 27 Feb 2017 11:20:54 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 38DFA113860A; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:40 +0100 Message-Id: <1488194450-28056-15-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 14/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 148819484947471.41092687459354; Mon, 27 Feb 2017 03:27:29 -0800 (PST) Received: from localhost ([::1]:51796 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJSi-0003HG-4x for importer@patchew.org; Mon, 27 Feb 2017 06:27:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44634) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00066Q-0W for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMT-00011R-Rh for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51328) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vN-DA; Mon, 27 Feb 2017 06:20:56 -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 779D7C05AA61; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtQO021134 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 3BD0B113860D; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:41 +0100 Message-Id: <1488194450-28056-16-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 15/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 1488194863484391.0112548765719; Mon, 27 Feb 2017 03:27:43 -0800 (PST) Received: from localhost ([::1]:51798 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJSv-0003Vx-21 for importer@patchew.org; Mon, 27 Feb 2017 06:27:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44546) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMU-00063w-8z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMS-0000zf-7I for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34362) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000va-GH; Mon, 27 Feb 2017 06:20:56 -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 90EEEC0A8054; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtB6030344 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 3EB151138610; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:42 +0100 Message-Id: <1488194450-28056-17-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 16/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 148819538172233.590811106065416; Mon, 27 Feb 2017 03:36:21 -0800 (PST) Received: from localhost ([::1]:51849 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJbI-0002ra-9D for importer@patchew.org; Mon, 27 Feb 2017 06:36:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44811) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMc-0006FQ-By for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMa-00018L-63 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47278) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vP-EK; Mon, 27 Feb 2017 06:20:56 -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 8256280489; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtI9030347 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 4199D1138613; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:43 +0100 Message-Id: <1488194450-28056-18-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 17/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster --- include/qapi/qobject-input-visitor.h | 12 ++++++++++++ qapi/qobject-input-visitor.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 45 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 3db5850..64a08d3 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 */ @@ -655,3 +657,34 @@ 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(optarg, implied_key, errp); + v =3D qobject_input_visitor_new_keyval(QOBJECT(args)); + } + QDECREF(args); + + return v; +} --=20 2.7.4 From nobody Sat May 4 04:06:39 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 1488196194043537.5960008472109; Mon, 27 Feb 2017 03:49:54 -0800 (PST) Received: from localhost ([::1]:51933 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJoO-0006ps-ND for importer@patchew.org; Mon, 27 Feb 2017 06:49:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44770) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DP-3u for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMW-00014T-4j for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34370) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vo-Jm; Mon, 27 Feb 2017 06:20:56 -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 B5E41C02C017; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtKK003143 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 47B2E1138616; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:44 +0100 Message-Id: <1488194450-28056-19-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.31]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 18/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- qemu-options.hx | 7 +++++++ vl.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index bf458f8..8f02264 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[,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..0684d52 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); @@ -4454,6 +4483,16 @@ int main(int argc, char **argv, char **envp) qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, NULL); } + 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 (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine_class->block_default_type, NULL)) { exit(1); --=20 2.7.4 From nobody Sat May 4 04:06:39 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 1488195688323733.6502272758993; Mon, 27 Feb 2017 03:41:28 -0800 (PST) Received: from localhost ([::1]:51876 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJgC-0007TH-Ot for importer@patchew.org; Mon, 27 Feb 2017 06:41:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44667) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00067k-Oo for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMU-00012T-Da for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34360) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vR-Ea; Mon, 27 Feb 2017 06:20:56 -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 7AB7FC0A8052; Mon, 27 Feb 2017 11:20:56 +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 v1RBKt9v003144 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 4CBBF1138619; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:45 +0100 Message-Id: <1488194450-28056-20-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.31]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 19/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 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 --- 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 64a08d3..1d7b420 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); @@ -478,6 +487,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) { @@ -649,7 +667,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 Sat May 4 04:06:39 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 148819567175556.70624024538074; Mon, 27 Feb 2017 03:41:11 -0800 (PST) Received: from localhost ([::1]:51875 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJfx-0007EK-DT for importer@patchew.org; Mon, 27 Feb 2017 06:41:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44767) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DK-2b for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMW-000156-Oz for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49334) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vc-Jf; Mon, 27 Feb 2017 06:20:56 -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 A51677E9F1; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtIx019472 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 50F08113861C; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:46 +0100 Message-Id: <1488194450-28056-21-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 20/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 Sat May 4 04:06:39 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 1488195106525222.8647571441336; Mon, 27 Feb 2017 03:31:46 -0800 (PST) Received: from localhost ([::1]:51822 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJWp-0007GD-Q3 for importer@patchew.org; Mon, 27 Feb 2017 06:31:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DN-3F for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMV-00013H-4Z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45006) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vQ-EO; Mon, 27 Feb 2017 06:20:56 -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 89B1880F96; Mon, 27 Feb 2017 11:20:56 +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 v1RBKt7q019473 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 54496113861F; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:47 +0100 Message-Id: <1488194450-28056-22-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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.27]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 21/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 2171e4a..2b8301e 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 @@ -733,6 +735,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 Sat May 4 04:06:39 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 1488195937269822.285542226423; Mon, 27 Feb 2017 03:45:37 -0800 (PST) Received: from localhost ([::1]:51896 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJkF-00030N-33 for importer@patchew.org; Mon, 27 Feb 2017 06:45:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44768) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMb-0006DM-31 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMV-00013r-Ga for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34468) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vg-ID; Mon, 27 Feb 2017 06:20:56 -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 AD9AB51458; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtxc009540 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 5766C1138541; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:48 +0100 Message-Id: <1488194450-28056-23-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 22/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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..53b27e2 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 and hyphen. + * 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 Sat May 4 04:06:39 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 1488195402681289.121458851513; Mon, 27 Feb 2017 03:36:42 -0800 (PST) Received: from localhost ([::1]:51850 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJbd-0003AF-9W for importer@patchew.org; Mon, 27 Feb 2017 06:36:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44663) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMW-00067j-O4 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMU-00012X-F7 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57640) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vU-Ef; Mon, 27 Feb 2017 06:20:56 -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 8C9F27FB73; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtZL009542 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 5A8A011384AC; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:49 +0100 Message-Id: <1488194450-28056-24-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-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]); Mon, 27 Feb 2017 11:20:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 23/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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 --- 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 f6496d7..6eceafb 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 3904c39..1170dad 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 /* @@ -115,6 +117,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 @@ -134,9 +137,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 Sat May 4 04:06:39 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 1488196540767661.6098839290986; Mon, 27 Feb 2017 03:55:40 -0800 (PST) Received: from localhost ([::1]:51970 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJtz-0003Yz-5e for importer@patchew.org; Mon, 27 Feb 2017 06:55:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44834) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciJMd-0006Gn-QQ for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciJMb-00018r-Eu for qemu-devel@nongnu.org; Mon, 27 Feb 2017 06:21:11 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51330) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciJMO-0000vr-Q5; Mon, 27 Feb 2017 06:20:57 -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 EEC43C054C3C; Mon, 27 Feb 2017 11:20:56 +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 v1RBKtWX021136 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 06:20:56 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 5DEAA11384AE; Mon, 27 Feb 2017 12:20:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 12:20:50 +0100 Message-Id: <1488194450-28056-25-git-send-email-armbru@redhat.com> In-Reply-To: <1488194450-28056-1-git-send-email-armbru@redhat.com> References: <1488194450-28056-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 27 Feb 2017 11:20:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 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: , Cc: kwolf@redhat.com, "mdroth@linux.vnet.ibm.commdroth"@linux.vnet.ibm.com, pkrempa@redhat.com, qemu-block@nongnu.org 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 now 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 --- qapi/qobject-input-visitor.c | 5 +- tests/test-keyval.c | 117 ++++++++++++++++++++++++++++ util/keyval.c | 177 +++++++++++++++++++++++++++++++++++++++= +--- 3 files changed, 286 insertions(+), 13 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 1d7b420..4c159e0 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; diff --git a/tests/test-keyval.c b/tests/test-keyval.c index 6eceafb..1ff6035 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,71 @@ 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]); + } + 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.2=3Dzwei", NU= LL, &err); + error_free_or_abort(&err); + g_assert(!qdict); +} + static void test_keyval_visit_bool(void) { Error *err =3D NULL; @@ -459,6 +525,55 @@ 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, ""); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, "I"); + visit_start_list(v, NULL, NULL, 0, &error_abort); + visit_type_str(v, NULL, &s, &error_abort); + g_assert_cmpstr(s, =3D=3D, "II"); + 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"); + 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 +607,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 1170dad..3621f28 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 / [^,]* / * * 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. @@ -113,7 +141,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; @@ -137,8 +165,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); @@ -205,6 +238,119 @@ 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, 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); + elt =3D g_new0(QObject *, nelt); + 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); + /* + * We iterate @nelt times. Because the dictionary keys are + * distinct, the indexes are also distinct (key_to_index() + * ensures it). If we get one exceeding @nelt here, we will + * leave a hole in @elt[], triggering the error in the next + * loop. + * + * Well, I lied. key_to_index() can return INT_MAX multiple + * times, but INT_MAX surely exceeds @nelt. + */ + if ((size_t)index >=3D nelt) { + continue; + } + assert(!elt[index]); + elt[index] =3D ent->value; + qobject_incref(elt[index]); + } + + /* Make a list from @elt[] */ + list =3D qlist_new(); + for (i =3D 0; i < nelt; i++) { + if (!elt[i]) { + key =3D reassemble_key(key_of_cur); + error_setg(errp, "Parameter '%s%d' missing", key, i); + g_free(key); + QDECREF(list); + return NULL; + } + qlist_append_obj(list, elt[i]); + } + + 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 @@ -216,6 +362,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; @@ -228,5 +375,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