qapi: Fix to reject 'data': 'mumble' in struct
A struct's 'data' must be a JSON object defining the struct's members. The QAPI code generator incorrectly accepts a JSON string instead, and then crashes in QAPISchema._make_members() called from ._def_struct_type(). Fix to reject it: factor check_type_implicit() out of check_type_name_or_implicit(), and switch check_struct() to use it instead. Also add a test case. Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20230316071325.492471-9-armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> [More detailed commit message]
This commit is contained in:
parent
6f2ab6090d
commit
e2050ef633
@ -354,14 +354,14 @@ def check_type_name_or_array(value: Optional[object],
|
||||
source)
|
||||
|
||||
|
||||
def check_type_name_or_implicit(value: Optional[object],
|
||||
info: QAPISourceInfo, source: str,
|
||||
parent_name: Optional[str]) -> None:
|
||||
def check_type_implicit(value: Optional[object],
|
||||
info: QAPISourceInfo, source: str,
|
||||
parent_name: Optional[str]) -> None:
|
||||
"""
|
||||
Normalize and validate an optional implicit struct type.
|
||||
|
||||
Accept ``None``, ``str``, or a ``dict`` defining an implicit
|
||||
struct type. The latter is normalized in place.
|
||||
Accept ``None`` or a ``dict`` defining an implicit struct type.
|
||||
The latter is normalized in place.
|
||||
|
||||
:param value: The value to check.
|
||||
:param info: QAPI schema source file information.
|
||||
@ -377,9 +377,6 @@ def check_type_name_or_implicit(value: Optional[object],
|
||||
if value is None:
|
||||
return
|
||||
|
||||
if isinstance(value, str):
|
||||
return
|
||||
|
||||
if not isinstance(value, dict):
|
||||
raise QAPISemError(info,
|
||||
"%s should be an object or type name" % source)
|
||||
@ -401,6 +398,15 @@ def check_type_name_or_implicit(value: Optional[object],
|
||||
check_type_name_or_array(arg['type'], info, key_source)
|
||||
|
||||
|
||||
def check_type_name_or_implicit(value: Optional[object],
|
||||
info: QAPISourceInfo, source: str,
|
||||
parent_name: Optional[str]) -> None:
|
||||
if value is None or isinstance(value, str):
|
||||
return
|
||||
|
||||
check_type_implicit(value, info, source, parent_name)
|
||||
|
||||
|
||||
def check_features(features: Optional[object],
|
||||
info: QAPISourceInfo) -> None:
|
||||
"""
|
||||
@ -486,7 +492,7 @@ def check_struct(expr: QAPIExpression) -> None:
|
||||
name = cast(str, expr['struct']) # Checked in check_exprs
|
||||
members = expr['data']
|
||||
|
||||
check_type_name_or_implicit(members, expr.info, "'data'", name)
|
||||
check_type_implicit(members, expr.info, "'data'", name)
|
||||
check_type_name(expr.get('base'), expr.info, "'base'")
|
||||
|
||||
|
||||
|
@ -164,6 +164,7 @@ schemas = [
|
||||
'struct-base-clash-deep.json',
|
||||
'struct-base-clash.json',
|
||||
'struct-data-invalid.json',
|
||||
'struct-data-typename.json',
|
||||
'struct-member-if-invalid.json',
|
||||
'struct-member-invalid-dict.json',
|
||||
'struct-member-invalid.json',
|
||||
|
2
tests/qapi-schema/struct-data-typename.err
Normal file
2
tests/qapi-schema/struct-data-typename.err
Normal file
@ -0,0 +1,2 @@
|
||||
struct-data-typename.json: In struct 'Stru2':
|
||||
struct-data-typename.json:2: 'data' should be an object or type name
|
2
tests/qapi-schema/struct-data-typename.json
Normal file
2
tests/qapi-schema/struct-data-typename.json
Normal file
@ -0,0 +1,2 @@
|
||||
{ 'struct': 'Stru1', 'data': {} }
|
||||
{ 'struct': 'Stru2', 'data': 'Stru1' }
|
0
tests/qapi-schema/struct-data-typename.out
Normal file
0
tests/qapi-schema/struct-data-typename.out
Normal file
Loading…
Reference in New Issue
Block a user