diff options
| author | Chuck Lever <cel@kernel.org> | 2026-07-12 16:34:50 -0400 |
|---|---|---|
| committer | Chuck Lever <cel@kernel.org> | 2026-08-10 09:54:35 -0400 |
| commit | 69b89515b16b539ce64e196e04dee56908370f09 (patch) | |
| tree | 82e86a91b1e6e832382bdff1e300d152b44e9314 /tools/net | |
| parent | b75e1a256d9ed2425ad648fe4e17b9c89c415ec3 (diff) | |
| download | linux-next-69b89515b16b539ce64e196e04dee56908370f09.tar.gz linux-next-69b89515b16b539ce64e196e04dee56908370f09.zip | |
xdrgen: Enforce RFC 5531 name and number scoping for RPC programs
The duplicate-identifier check enforces the RFC 4506 name space
for XDR type and constant identifiers but ignores what an RPC
program definition adds. RFC 5531 Section 12.3 completes the
model: a program identifier shares the specification-wide name
space with constant and type identifiers, a version name and
number are unique within their program, and a procedure name and
number are unique within their version.
xdrgen currently accepts a specification that breaks any of these
rules, and the symptom depends on which rule. A duplicate procedure
name reaches the generated header as a redeclared enumerator,
which the C compiler rejects. A duplicate procedure number is
more dangerous because it is silent: the two procedures emit
enumerators of equal value -- valid C that compiles cleanly --
leaving a dispatch collision to surface only at run time. A
duplicate program name shares the specification-wide name space
with constants and types and is caught alongside them.
Extend the check to enforce RFC 5531 scoping in full.
Link: https://patch.msgid.link/20260712203451.124902-5-cel@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
Diffstat (limited to 'tools/net')
| -rw-r--r-- | tools/net/sunrpc/xdrgen/xdr_ast.py | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/tools/net/sunrpc/xdrgen/xdr_ast.py b/tools/net/sunrpc/xdrgen/xdr_ast.py index cf68ff5dfe17..ec48506b239a 100644 --- a/tools/net/sunrpc/xdrgen/xdr_ast.py +++ b/tools/net/sunrpc/xdrgen/xdr_ast.py @@ -862,6 +862,50 @@ def _introduced_names(value): yield value.declaration.name, value.declaration elif isinstance(value, _XdrConstant): yield value.name, value + elif isinstance(value, _RpcProgram): + yield value.name, value + + +def _check_rpc_scope_names(program: "_RpcProgram") -> None: + """Enforce RFC 5531 Section 12.3 scoping within an RPC program. + + A version name and number are unique within the program and a + procedure name and number are unique within its version. + """ + version_names = set() + version_numbers = set() + for version in program.versions: + if version.name in version_names: + raise XdrSemanticError( + f"duplicate version name '{version.name}'" + f" in program '{program.name}'", + version, + ) + version_names.add(version.name) + if version.number in version_numbers: + raise XdrSemanticError( + f"duplicate version number {version.number}" + f" in program '{program.name}'", + version, + ) + version_numbers.add(version.number) + procedure_names = set() + procedure_numbers = set() + for procedure in version.procedures: + if procedure.name in procedure_names: + raise XdrSemanticError( + f"duplicate procedure name '{procedure.name}'" + f" in version '{version.name}'", + procedure, + ) + procedure_names.add(procedure.name) + if procedure.number in procedure_numbers: + raise XdrSemanticError( + f"duplicate procedure number {procedure.number}" + f" in version '{version.name}'", + procedure, + ) + procedure_numbers.add(procedure.number) def check_duplicate_definitions(root: "Specification") -> None: @@ -869,6 +913,9 @@ def check_duplicate_definitions(root: "Specification") -> None: RFC 4506 Section 6.4 places constant and type identifiers in a single name space that must be unique within a specification. + RFC 5531 Section 12.3 adds RPC program names to that name space + and scopes version names and numbers to their program and + procedure names and numbers to their version. """ seen = {} for definition in root.definitions: @@ -882,6 +929,8 @@ def check_duplicate_definitions(root: "Specification") -> None: where, ) seen[name] = where + if isinstance(definition.value, _RpcProgram): + _check_rpc_scope_names(definition.value) def transform_parse_tree(parse_tree): |
