提交 59a92fee 编写于 作者: E Eric Blake 提交者: Markus Armbruster

qapi: Tighten the regex on valid names

We already documented that qapi names should match specific
patterns (such as starting with a letter unless it was an enum
value or a downstream extension).  Tighten that from a suggestion
into a hard requirement, which frees up names beginning with a
single underscore for qapi internal usage.

The tighter regex doesn't forbid everything insane that a user
could provide (for example, a user could name a type 'Foo-lookup'
to collide with the generated 'Foo_lookup[]' for an enum 'Foo'),
but does a good job at protecting the most obvious uses, and
also happens to reserve single leading underscore for later use.

The handling of enum values starting with a digit is tricky:
commit 9fb081e0 introduced a subtle bug by using c_name() on
a munged value, which would allow an enum to include the
member 'q-int' in spite of our reservation.  Furthermore,
munging with a leading '_' would fail our tighter regex.  So
fix it by only munging for leading digits (which are never
ticklish in c_name()) and by using a different prefix (I
picked 'D', although any letter should do).

Add new tests, reserved-member-underscore and reserved-enum-q,
to demonstrate the tighter checking.
Signed-off-by: NEric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-22-git-send-email-eblake@redhat.com>
Message-Id: <1447883135-18020-1-git-send-email-eblake@redhat.com>
[Eric's fixup squashed in]
Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
上级 5be5b776
...@@ -118,17 +118,17 @@ tracking optional fields. ...@@ -118,17 +118,17 @@ tracking optional fields.
Any name (command, event, type, field, or enum value) beginning with Any name (command, event, type, field, or enum value) beginning with
"x-" is marked experimental, and may be withdrawn or changed "x-" is marked experimental, and may be withdrawn or changed
incompatibly in a future release. Downstream vendors may add incompatibly in a future release. All names must begin with a letter,
extensions; such extensions should begin with a prefix matching and contain only ASCII letters, digits, dash, and underscore. There
"__RFQDN_" (for the reverse-fully-qualified-domain-name of the are two exceptions: enum values may start with a digit, and any
vendor), even if the rest of the name uses dash (example: extensions added by downstream vendors should start with a prefix
__com.redhat_drive-mirror). Other than downstream extensions (with matching "__RFQDN_" (for the reverse-fully-qualified-domain-name of
leading underscore and the use of dots), all names should begin with a the vendor), even if the rest of the name uses dash (example:
letter, and contain only ASCII letters, digits, dash, and underscore. __com.redhat_drive-mirror). Names beginning with 'q_' are reserved
Names beginning with 'q_' are reserved for the generator: QMP names for the generator: QMP names that resemble C keywords or other
that resemble C keywords or other problematic strings will be munged problematic strings will be munged in C to use this prefix. For
in C to use this prefix. For example, a field named "default" in example, a field named "default" in qapi becomes "q_default" in the
qapi becomes "q_default" in the generated C code. generated C code.
In the rest of this document, usage lines are given for each In the rest of this document, usage lines are given for each
expression type, with literal strings written in lower case and expression type, with literal strings written in lower case and
......
...@@ -353,9 +353,11 @@ def discriminator_find_enum_define(expr): ...@@ -353,9 +353,11 @@ def discriminator_find_enum_define(expr):
return find_enum(discriminator_type) return find_enum(discriminator_type)
# FIXME should enforce "other than downstream extensions [...], all # Names must be letters, numbers, -, and _. They must start with letter,
# names should begin with a letter". # except for downstream extensions which must start with __RFQDN_.
valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$') # Dots are only valid in the downstream extension prefix.
valid_name = re.compile('^(__[a-zA-Z0-9.-]+_)?'
'[a-zA-Z][a-zA-Z0-9_-]*$')
def check_name(expr_info, source, name, allow_optional=False, def check_name(expr_info, source, name, allow_optional=False,
...@@ -374,8 +376,8 @@ def check_name(expr_info, source, name, allow_optional=False, ...@@ -374,8 +376,8 @@ def check_name(expr_info, source, name, allow_optional=False,
% (source, name)) % (source, name))
# Enum members can start with a digit, because the generated C # Enum members can start with a digit, because the generated C
# code always prefixes it with the enum name # code always prefixes it with the enum name
if enum_member: if enum_member and membername[0].isdigit():
membername = '_' + membername membername = 'D' + membername
# Reserve the entire 'q_' namespace for c_name() # Reserve the entire 'q_' namespace for c_name()
if not valid_name.match(membername) or \ if not valid_name.match(membername) or \
c_name(membername, False).startswith('q_'): c_name(membername, False).startswith('q_'):
......
...@@ -318,9 +318,11 @@ qapi-schema += redefined-command.json ...@@ -318,9 +318,11 @@ qapi-schema += redefined-command.json
qapi-schema += redefined-event.json qapi-schema += redefined-event.json
qapi-schema += redefined-type.json qapi-schema += redefined-type.json
qapi-schema += reserved-command-q.json qapi-schema += reserved-command-q.json
qapi-schema += reserved-enum-q.json
qapi-schema += reserved-member-has.json qapi-schema += reserved-member-has.json
qapi-schema += reserved-member-q.json qapi-schema += reserved-member-q.json
qapi-schema += reserved-member-u.json qapi-schema += reserved-member-u.json
qapi-schema += reserved-member-underscore.json
qapi-schema += reserved-type-kind.json qapi-schema += reserved-type-kind.json
qapi-schema += reserved-type-list.json qapi-schema += reserved-type-list.json
qapi-schema += returns-alternate.json qapi-schema += returns-alternate.json
......
tests/qapi-schema/reserved-enum-q.json:4: Member of enum 'Foo' uses invalid name 'q-Unix'
# C entity name collision
# We reject names like 'q-unix', because they can collide with the mangled
# name for 'unix' in generated C.
{ 'enum': 'Foo', 'data': [ 'unix', 'q-Unix' ] }
tests/qapi-schema/reserved-member-underscore.json:4: Member of 'data' for struct 'Oops' uses invalid name '_oops'
# C member name collision
# We reject use of a single leading underscore in all names (names must
# begin with a letter or a downstream extension double-underscore prefix).
{ 'struct': 'Oops', 'data': { '_oops': 'str' } }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册