summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorEduardo Habkost <ehabkost@redhat.com>2017-07-17 15:09:26 -0300
committerMarkus Armbruster <armbru@redhat.com>2017-09-01 12:51:04 +0200
commitfda72ab4510bcc680a3c4fe55997aa29589884f7 (patch)
tree40cf0dcb520d573ee06aa48fb4ae314bd378cd5f
parent223cd0e13f2e46078d7b573f0b8402bfbee339be (diff)
downloadfocaccia-qemu-fda72ab4510bcc680a3c4fe55997aa29589884f7.tar.gz
focaccia-qemu-fda72ab4510bcc680a3c4fe55997aa29589884f7.zip
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 <module>
      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 <ehabkost@redhat.com>
Message-Id: <20170717180926.14924-1-ehabkost@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
-rw-r--r--scripts/qapi.py8
-rw-r--r--tests/Makefile.include2
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.err1
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.json4
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.out0
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.err1
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.json4
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.out0
10 files changed, 18 insertions, 4 deletions
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 8aa2775f12..3693b520da 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
 
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index f08b7418f0..00af45ca85 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -376,6 +376,8 @@ qapi-schema += alternate-conflict-dict.json
 qapi-schema += alternate-conflict-enum-bool.json
 qapi-schema += alternate-conflict-enum-int.json
 qapi-schema += alternate-conflict-string.json
+qapi-schema += alternate-conflict-bool-string.json
+qapi-schema += alternate-conflict-num-string.json
 qapi-schema += alternate-empty.json
 qapi-schema += alternate-nested.json
 qapi-schema += alternate-unknown.json
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.err b/tests/qapi-schema/alternate-conflict-bool-string.err
new file mode 100644
index 0000000000..e52fee7620
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-bool-string.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-conflict-bool-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.exit b/tests/qapi-schema/alternate-conflict-bool-string.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-bool-string.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.json b/tests/qapi-schema/alternate-conflict-bool-string.json
new file mode 100644
index 0000000000..0544de10f3
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-bool-string.json
@@ -0,0 +1,4 @@
+# alternate branches of 'str' type conflict with all scalar types
+{ 'alternate': 'Alt',
+  'data': { 'one': 'bool',
+            'two': 'str' } }
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.out b/tests/qapi-schema/alternate-conflict-bool-string.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-bool-string.out
diff --git a/tests/qapi-schema/alternate-conflict-num-string.err b/tests/qapi-schema/alternate-conflict-num-string.err
new file mode 100644
index 0000000000..5ba3827dd1
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-num-string.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-conflict-num-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
diff --git a/tests/qapi-schema/alternate-conflict-num-string.exit b/tests/qapi-schema/alternate-conflict-num-string.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-num-string.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/alternate-conflict-num-string.json b/tests/qapi-schema/alternate-conflict-num-string.json
new file mode 100644
index 0000000000..ae901449af
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-num-string.json
@@ -0,0 +1,4 @@
+# alternate branches of 'str' type conflict with all scalar types
+{ 'alternate': 'Alt',
+  'data': { 'one': 'number',
+            'two': 'str' } }
diff --git a/tests/qapi-schema/alternate-conflict-num-string.out b/tests/qapi-schema/alternate-conflict-num-string.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/alternate-conflict-num-string.out