summaryrefslogtreecommitdiff
path: root/tools/net
diff options
context:
space:
mode:
authorChuck Lever <cel@kernel.org>2026-07-12 16:34:50 -0400
committerChuck Lever <cel@kernel.org>2026-08-10 09:54:35 -0400
commit69b89515b16b539ce64e196e04dee56908370f09 (patch)
tree82e86a91b1e6e832382bdff1e300d152b44e9314 /tools/net
parentb75e1a256d9ed2425ad648fe4e17b9c89c415ec3 (diff)
downloadlinux-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.py49
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):