From fda72ab4510bcc680a3c4fe55997aa29589884f7 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 17 Jul 2017 15:09:26 -0300 Subject: qapi: Fix error handling code on alternate conflict The conflict check added by commit c0644771 ("qapi: Reject alternates that can't work with keyval_parse()") doesn't work with the following declaration: { 'alternate': 'Alt', 'data': { 'one': 'bool', 'two': 'str' } } It crashes with: Traceback (most recent call last): File "./scripts/qapi-types.py", line 295, in schema = QAPISchema(input_file) File "/home/ehabkost/rh/proj/virt/qemu/scripts/qapi.py", line 1468, in __init__ self.exprs = check_exprs(parser.exprs) File "/home/ehabkost/rh/proj/virt/qemu/scripts/qapi.py", line 958, in check_exprs check_alternate(expr, info) File "/home/ehabkost/rh/proj/virt/qemu/scripts/qapi.py", line 830, in check_alternate % (name, key, types_seen[qtype])) KeyError: 'QTYPE_QSTRING' This happens because the previously-seen conflicting member ('one') can't be found at types_seen[qtype], but at types_seen['QTYPE_BOOL']. Fix the bug by moving the error check to the same loop that adds new items to types_seen, raising an exception if types_seen[qt] is already set. Add two additional test cases that can detect the bug. Signed-off-by: Eduardo Habkost Message-Id: <20170717180926.14924-1-ehabkost@redhat.com> Signed-off-by: Markus Armbruster --- scripts/qapi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi.py b/scripts/qapi.py index 8aa2775..3693b52 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -825,11 +825,11 @@ def check_alternate(expr, info): else: conflicting.add('QTYPE_QNUM') conflicting.add('QTYPE_QBOOL') - if conflicting & set(types_seen): - raise QAPISemError(info, "Alternate '%s' member '%s' can't " - "be distinguished from member '%s'" - % (name, key, types_seen[qtype])) for qt in conflicting: + if qt in types_seen: + raise QAPISemError(info, "Alternate '%s' member '%s' can't " + "be distinguished from member '%s'" + % (name, key, types_seen[qt])) types_seen[qt] = key -- cgit v1.1 From 0f9afc2a8b5e78e511d79c936aa7b36deb3508bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 25 Aug 2017 12:59:00 +0200 Subject: qdict: Add qdict_put_null() helper, and put it to use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster Message-Id: <20170825105913.4060-2-marcandre.lureau@redhat.com> [Update to qobject.cocci squashed in, commit message tweaked] Signed-off-by: Markus Armbruster --- scripts/coccinelle/qobject.cocci | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.cocci index c518caf..1120eb1 100644 --- a/scripts/coccinelle/qobject.cocci +++ b/scripts/coccinelle/qobject.cocci @@ -20,6 +20,9 @@ expression Obj, Key, E; | - qdict_put(Obj, Key, qstring_from_str(E)); + qdict_put_str(Obj, Key, E); +| +- qdict_put(Obj, Key, qnull()); ++ qdict_put_null(Obj, Key); ) // Use QList macros where they make sense -- cgit v1.1 From 5b5f825d44306b18509cd10ba9ac6983e90d6e0f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 24 Aug 2017 10:46:07 +0200 Subject: qapi: Generate FOO_str() macro for QAPI enum FOO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next commit will put it to use. May look pointless now, but we're going to change the FOO_lookup's type, and then it'll help. Signed-off-by: Markus Armbruster Message-Id: <1503564371-26090-13-git-send-email-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- scripts/qapi-event.py | 1 + scripts/qapi-types.py | 4 ++++ scripts/qapi.py | 3 +++ 3 files changed, 8 insertions(+) (limited to 'scripts') diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index bcbef10..07b4b70 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -217,6 +217,7 @@ fdef.write(mcgen(''' fdecl.write(mcgen(''' #include "qapi/error.h" +#include "qapi/util.h" #include "qapi/qmp/qdict.h" #include "%(prefix)sqapi-types.h" diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index b45e7b5..7e3051d 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -292,6 +292,10 @@ fdef.write(mcgen(''' ''', prefix=prefix)) +fdecl.write(mcgen(''' +#include "qapi/util.h" +''')) + schema = QAPISchema(input_file) gen = QAPISchemaGenTypeVisitor() schema.visit(gen) diff --git a/scripts/qapi.py b/scripts/qapi.py index 3693b52..8736b9c 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -1894,6 +1894,9 @@ typedef enum %(c_name)s { ret += mcgen(''' +#define %(c_name)s_str(val) \\ + qapi_enum_lookup(%(c_name)s_lookup, (val)) + extern const char *const %(c_name)s_lookup[]; ''', c_name=c_name(name)) -- cgit v1.1 From f7abe0ecd4973dfe36944b916c5b9cf8ec199b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 24 Aug 2017 10:46:10 +0200 Subject: qapi: Change data type of the FOO_lookup generated for enum FOO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, a FOO_lookup is an array of strings terminated by a NULL sentinel. A future patch will generate enums with "holes". NULL-termination will cease to work then. To prepare for that, store the length in the FOO_lookup by wrapping it in a struct and adding a member for the length. The sentinel will be dropped next. Signed-off-by: Marc-André Lureau Message-Id: <20170822132255.23945-13-marcandre.lureau@redhat.com> [Basically redone] Signed-off-by: Markus Armbruster Message-Id: <1503564371-26090-16-git-send-email-armbru@redhat.com> [Rebased] --- scripts/qapi-visit.py | 2 +- scripts/qapi.py | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index bd0b742..7e1cfc1 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -153,7 +153,7 @@ def gen_visit_enum(name): void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s *obj, Error **errp) { int value = *obj; - visit_type_enum(v, name, &value, %(c_name)s_lookup, errp); + visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp); *obj = value; } ''', diff --git a/scripts/qapi.py b/scripts/qapi.py index 8736b9c..39a6727 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -1849,19 +1849,22 @@ def guardend(name): def gen_enum_lookup(name, values, prefix=None): ret = mcgen(''' -const char *const %(c_name)s_lookup[] = { +const QEnumLookup %(c_name)s_lookup = { + .array = (const char *const[]) { ''', c_name=c_name(name)) for value in values: index = c_enum_const(name, value, prefix) ret += mcgen(''' - [%(index)s] = "%(value)s", + [%(index)s] = "%(value)s", ''', index=index, value=value) max_index = c_enum_const(name, '_MAX', prefix) ret += mcgen(''' - [%(max_index)s] = NULL, + [%(max_index)s] = NULL, + }, + .size = %(max_index)s }; ''', max_index=max_index) @@ -1895,9 +1898,9 @@ typedef enum %(c_name)s { ret += mcgen(''' #define %(c_name)s_str(val) \\ - qapi_enum_lookup(%(c_name)s_lookup, (val)) + qapi_enum_lookup(&%(c_name)s_lookup, (val)) -extern const char *const %(c_name)s_lookup[]; +extern const QEnumLookup %(c_name)s_lookup; ''', c_name=c_name(name)) return ret -- cgit v1.1 From ebf677c8497ee81537f7ce57b165c978511ccde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 24 Aug 2017 10:46:11 +0200 Subject: qapi: drop the sentinel in enum array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all usages have been converted to user lookup helpers. Signed-off-by: Marc-André Lureau Message-Id: <20170822132255.23945-14-marcandre.lureau@redhat.com> [Rebased, superfluous local variable dropped, missing check-qom-proplist.c update added] Signed-off-by: Markus Armbruster Message-Id: <1503564371-26090-17-git-send-email-armbru@redhat.com> --- scripts/qapi.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi.py b/scripts/qapi.py index 39a6727..62dc52e 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -1860,14 +1860,12 @@ const QEnumLookup %(c_name)s_lookup = { ''', index=index, value=value) - max_index = c_enum_const(name, '_MAX', prefix) ret += mcgen(''' - [%(max_index)s] = NULL, }, .size = %(max_index)s }; ''', - max_index=max_index) + max_index=c_enum_const(name, '_MAX', prefix)) return ret -- cgit v1.1