qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v9 01/17] qapi: Add tests for reserved name abuse


From: Eric Blake
Subject: [Qemu-devel] [PATCH v9 01/17] qapi: Add tests for reserved name abuse
Date: Thu, 15 Oct 2015 22:15:26 -0600

A future patch wants to change qapi union representation from
an anonymous C union over to a named C union 'u', so that the
C names of tag values are in a separate namespace and thus
cannot collide with the C names of non-variant QMP members.
But for that to not cause any problems with future extensions
to existing qapi, it would be best if we prohibit 'u' as a
member name everywhere, to reserve it for our internal use.
(Remember that although 'u' would only actually collide in
flat unions, we must also worry about the fact that it is
possible to convert from a struct to a flat union in a future
qemu version while remaining backwards-compatible in QMP.)

We are failing to detect a collision between a QMP member and
the implicit 'has_*' flag for another optional QMP member. The
easiest fix would be for a future patch to reserve the entire
"has[-_]" namespace for member names (also for branch names,
but only as long as branch names can collide with QMP names).

Our current representation of qapi arrays is done by appending
'List' to the element name; but we are not preventing the
creation of a non-array type with the same name.  It is also
possible to abuse the internal naming by writing such things
as ['intList'] for a 2-dimensional array of integers; however,
we may want to later add support for explicit 2D arrays such
as [['int']], so it is better to defer writing tests for what
we will permit and reject when it comes to multi-dimensioned
arrays until that later design is complete; for now, we are
only testing type collision.

On the other hand, there is no reason to forbid type name
patterns from member names, or member name patterns from types,
since the two are not in the same namespace in C and won't
collide.

Modify and add tests to cover these issues.

Signed-off-by: Eric Blake <address@hidden>

---
v9: new patch
---
 tests/Makefile                                 |  3 +++
 tests/qapi-schema/args-name-has.err            |  0
 tests/qapi-schema/args-name-has.exit           |  1 +
 tests/qapi-schema/args-name-has.json           |  6 ++++++
 tests/qapi-schema/args-name-has.out            |  6 ++++++
 tests/qapi-schema/flat-union-clash-branch.json | 17 +++++++----------
 tests/qapi-schema/flat-union-clash-branch.out  |  9 +++------
 tests/qapi-schema/qapi-schema-test.json        |  9 +++++++++
 tests/qapi-schema/qapi-schema-test.out         | 12 ++++++++++++
 tests/qapi-schema/struct-member-u.err          |  0
 tests/qapi-schema/struct-member-u.exit         |  1 +
 tests/qapi-schema/struct-member-u.json         |  6 ++++++
 tests/qapi-schema/struct-member-u.out          |  3 +++
 tests/qapi-schema/struct-name-list.err         |  0
 tests/qapi-schema/struct-name-list.exit        |  1 +
 tests/qapi-schema/struct-name-list.json        |  5 +++++
 tests/qapi-schema/struct-name-list.out         |  3 +++
 17 files changed, 66 insertions(+), 16 deletions(-)
 create mode 100644 tests/qapi-schema/args-name-has.err
 create mode 100644 tests/qapi-schema/args-name-has.exit
 create mode 100644 tests/qapi-schema/args-name-has.json
 create mode 100644 tests/qapi-schema/args-name-has.out
 create mode 100644 tests/qapi-schema/struct-member-u.err
 create mode 100644 tests/qapi-schema/struct-member-u.exit
 create mode 100644 tests/qapi-schema/struct-member-u.json
 create mode 100644 tests/qapi-schema/struct-member-u.out
 create mode 100644 tests/qapi-schema/struct-name-list.err
 create mode 100644 tests/qapi-schema/struct-name-list.exit
 create mode 100644 tests/qapi-schema/struct-name-list.json
 create mode 100644 tests/qapi-schema/struct-name-list.out

diff --git a/tests/Makefile b/tests/Makefile
index cb221de..ef2a19f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -241,6 +241,7 @@ qapi-schema += args-invalid.json
 qapi-schema += args-member-array-bad.json
 qapi-schema += args-member-unknown.json
 qapi-schema += args-name-clash.json
+qapi-schema += args-name-has.json
 qapi-schema += args-union.json
 qapi-schema += args-unknown.json
 qapi-schema += bad-base.json
@@ -323,6 +324,8 @@ qapi-schema += struct-base-clash-deep.json
 qapi-schema += struct-base-clash.json
 qapi-schema += struct-data-invalid.json
 qapi-schema += struct-member-invalid.json
+qapi-schema += struct-member-u.json
+qapi-schema += struct-name-list.json
 qapi-schema += trailing-comma-list.json
 qapi-schema += trailing-comma-object.json
 qapi-schema += type-bypass-bad-gen.json
diff --git a/tests/qapi-schema/args-name-has.err 
b/tests/qapi-schema/args-name-has.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/args-name-has.exit 
b/tests/qapi-schema/args-name-has.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/args-name-has.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/args-name-has.json 
b/tests/qapi-schema/args-name-has.json
new file mode 100644
index 0000000..a2197de
--- /dev/null
+++ b/tests/qapi-schema/args-name-has.json
@@ -0,0 +1,6 @@
+# C member name collision
+# FIXME - This parses, but fails to compile, because the C struct is given
+# two 'has_a' members, one from the flag for optional 'a', and the other
+# from member 'has-a'.  Either reject this at parse time, or munge the C
+# names to avoid the collision.
+{ 'command': 'oops', 'data': { '*a': 'str', 'has-a': 'str' } }
diff --git a/tests/qapi-schema/args-name-has.out 
b/tests/qapi-schema/args-name-has.out
new file mode 100644
index 0000000..5a18b6b
--- /dev/null
+++ b/tests/qapi-schema/args-name-has.out
@@ -0,0 +1,6 @@
+object :empty
+object :obj-oops-arg
+    member a: str optional=True
+    member has-a: str optional=False
+command oops :obj-oops-arg -> None
+   gen=True success_response=True
diff --git a/tests/qapi-schema/flat-union-clash-branch.json 
b/tests/qapi-schema/flat-union-clash-branch.json
index e593336..c9f08e3 100644
--- a/tests/qapi-schema/flat-union-clash-branch.json
+++ b/tests/qapi-schema/flat-union-clash-branch.json
@@ -1,18 +1,15 @@
 # Flat union branch name collision
-# FIXME: this parses, but then fails to compile due to a duplicate 'c_d'
-# (one from the base member, the other from the branch name).  We should
-# either reject the collision at parse time, or munge the generated branch
-# name to allow this to compile.
+# FIXME: this parses, but then fails to compile due to a duplicate 'has_a'
+# (one as the implicit flag for the optional base member, the other from
+# the C member for the branch name).  We should either reject the collision
+# at parse time, or munge the generated branch name to allow this to compile.
 { 'enum': 'TestEnum',
-  'data': [ 'base', 'c-d' ] }
+  'data': [ 'has-a' ] }
 { 'struct': 'Base',
-  'data': { 'enum1': 'TestEnum', '*c_d': 'str' } }
+  'data': { 'enum1': 'TestEnum', '*a': 'str' } }
 { 'struct': 'Branch1',
   'data': { 'string': 'str' } }
-{ 'struct': 'Branch2',
-  'data': { 'value': 'int' } }
 { 'union': 'TestUnion',
   'base': 'Base',
   'discriminator': 'enum1',
-  'data': { 'base': 'Branch1',
-            'c-d': 'Branch2' } }
+  'data': { 'has-a': 'Branch1' } }
diff --git a/tests/qapi-schema/flat-union-clash-branch.out 
b/tests/qapi-schema/flat-union-clash-branch.out
index 8e0da73..1491081 100644
--- a/tests/qapi-schema/flat-union-clash-branch.out
+++ b/tests/qapi-schema/flat-union-clash-branch.out
@@ -1,14 +1,11 @@
 object :empty
 object Base
     member enum1: TestEnum optional=False
-    member c_d: str optional=True
+    member a: str optional=True
 object Branch1
     member string: str optional=False
-object Branch2
-    member value: int optional=False
-enum TestEnum ['base', 'c-d']
+enum TestEnum ['has-a']
 object TestUnion
     base Base
     tag enum1
-    case base: Branch1
-    case c-d: Branch2
+    case has-a: Branch1
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index 4e2d7c2..c842e22 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -105,6 +105,15 @@
             'sizes': ['size'],
             'any': ['any'] } }

+# Even if 'u' is forbidden as a struct member name, it should still be
+# valid as a type or union branch name. And although '*Kind' is forbidden
+# as a type name, it should not be forbidden as a member or branch name.
+# TODO - '*List' should also be forbidden as a type name, and 'has_*' as
+# a member name.
+{ 'struct': 'has_a', 'data': { 'MyKind': 'int', 'MyList': ['int'] } }
+{ 'union': 'u', 'data': { 'u': 'uint8', 'myKind': 'has_a',
+                          'myList': 'has_a' } }
+
 # testing commands
 { 'command': 'user_def_cmd', 'data': {} }
 { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index a6c80e0..30c3ff0 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -22,6 +22,8 @@ object :obj-guest-get-time-arg
     member b: int optional=True
 object :obj-guest-sync-arg
     member arg: any optional=False
+object :obj-has_a-wrapper
+    member data: has_a optional=False
 object :obj-int16List-wrapper
     member data: int16List optional=False
 object :obj-int32List-wrapper
@@ -46,6 +48,8 @@ object :obj-uint32List-wrapper
     member data: uint32List optional=False
 object :obj-uint64List-wrapper
     member data: uint64List optional=False
+object :obj-uint8-wrapper
+    member data: uint8 optional=False
 object :obj-uint8List-wrapper
     member data: uint8List optional=False
 object :obj-user_def_cmd1-arg
@@ -191,6 +195,14 @@ command guest-get-time :obj-guest-get-time-arg -> int
    gen=True success_response=True
 command guest-sync :obj-guest-sync-arg -> any
    gen=True success_response=True
+object has_a
+    member MyKind: int optional=False
+    member MyList: intList optional=False
+object u
+    case u: :obj-uint8-wrapper
+    case myKind: :obj-has_a-wrapper
+    case myList: :obj-has_a-wrapper
+enum uKind ['u', 'myKind', 'myList']
 command user_def_cmd None -> None
    gen=True success_response=True
 command user_def_cmd1 :obj-user_def_cmd1-arg -> None
diff --git a/tests/qapi-schema/struct-member-u.err 
b/tests/qapi-schema/struct-member-u.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/struct-member-u.exit 
b/tests/qapi-schema/struct-member-u.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/struct-member-u.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/struct-member-u.json 
b/tests/qapi-schema/struct-member-u.json
new file mode 100644
index 0000000..d72023d
--- /dev/null
+++ b/tests/qapi-schema/struct-member-u.json
@@ -0,0 +1,6 @@
+# Potential C member name collision
+# FIXME - This parses and compiles, but would cause a collision if this
+# struct is later reworked to be part of a flat union, once unions hide
+# their tag values under a C union named 'u'. We should reject the use
+# of this identifier to reserve it for internal use.
+{ 'struct': 'Oops', 'data': { 'u': 'str' } }
diff --git a/tests/qapi-schema/struct-member-u.out 
b/tests/qapi-schema/struct-member-u.out
new file mode 100644
index 0000000..aa53e7f
--- /dev/null
+++ b/tests/qapi-schema/struct-member-u.out
@@ -0,0 +1,3 @@
+object :empty
+object Oops
+    member u: str optional=False
diff --git a/tests/qapi-schema/struct-name-list.err 
b/tests/qapi-schema/struct-name-list.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/struct-name-list.exit 
b/tests/qapi-schema/struct-name-list.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/struct-name-list.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/struct-name-list.json 
b/tests/qapi-schema/struct-name-list.json
new file mode 100644
index 0000000..8ad38e6
--- /dev/null
+++ b/tests/qapi-schema/struct-name-list.json
@@ -0,0 +1,5 @@
+# Potential C name collision
+# FIXME - This parses and compiles on its own, but prevents the user from
+# creating a type named 'Foo' and using ['Foo'] for an array.  We should
+# reject the use of any non-array type names ending in 'List'.
+{ 'struct': 'FooList', 'data': { 's': 'str' } }
diff --git a/tests/qapi-schema/struct-name-list.out 
b/tests/qapi-schema/struct-name-list.out
new file mode 100644
index 0000000..0406bfe
--- /dev/null
+++ b/tests/qapi-schema/struct-name-list.out
@@ -0,0 +1,3 @@
+object :empty
+object FooList
+    member s: str optional=False
-- 
2.4.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]