summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-procedure-number-negative.x20
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-procedure-number-too-large.x20
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-program-number-negative.x19
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-program-number-too-large.x19
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-version-number-negative.x19
-rw-r--r--tools/net/sunrpc/xdrgen/tests/bad-version-number-too-large.x19
-rw-r--r--tools/net/sunrpc/xdrgen/xdr_ast.py64
7 files changed, 177 insertions, 3 deletions
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-negative.x b/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-negative.x
new file mode 100644
index 000000000000..33ed272c3ce2
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-negative.x
@@ -0,0 +1,20 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 assigns only unsigned constants to program, version, and
+ * procedure numbers (Section 12.3). This spec gives a procedure a
+ * negative number, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * negative procedure number -5 in version 'BADVERS'
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-procedure-number-negative.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ void BADPROC_FOO(void) = -5;
+ } = 1;
+} = 100000;
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-too-large.x b/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-too-large.x
new file mode 100644
index 000000000000..521581c57358
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-procedure-number-too-large.x
@@ -0,0 +1,20 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 encodes program, version, and procedure numbers as unsigned
+ * 32-bit integers (Section 9). This spec gives a procedure a number one
+ * past the 32-bit maximum, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * procedure number 4294967296 in version 'BADVERS' exceeds 4294967295
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-procedure-number-too-large.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ void BADPROC_FOO(void) = 4294967296;
+ } = 1;
+} = 100000;
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-program-number-negative.x b/tools/net/sunrpc/xdrgen/tests/bad-program-number-negative.x
new file mode 100644
index 000000000000..f7b71ee07f6c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-program-number-negative.x
@@ -0,0 +1,19 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 assigns only unsigned constants to program, version, and
+ * procedure numbers (Section 12.3). This spec gives the program a
+ * negative number, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * negative program number -100000 in program 'BADPROG'
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-program-number-negative.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ } = 1;
+} = -100000;
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-program-number-too-large.x b/tools/net/sunrpc/xdrgen/tests/bad-program-number-too-large.x
new file mode 100644
index 000000000000..c761584e712f
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-program-number-too-large.x
@@ -0,0 +1,19 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 encodes program, version, and procedure numbers as unsigned
+ * 32-bit integers (Section 9). This spec gives the program a number one
+ * past the 32-bit maximum, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * program number 4294967296 in program 'BADPROG' exceeds 4294967295
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-program-number-too-large.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ } = 1;
+} = 4294967296;
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-version-number-negative.x b/tools/net/sunrpc/xdrgen/tests/bad-version-number-negative.x
new file mode 100644
index 000000000000..dd9c773435c0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-version-number-negative.x
@@ -0,0 +1,19 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 assigns only unsigned constants to program, version, and
+ * procedure numbers (Section 12.3). This spec gives the version a
+ * negative number, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * negative version number -1 in program 'BADPROG'
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-version-number-negative.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ } = -1;
+} = 100000;
diff --git a/tools/net/sunrpc/xdrgen/tests/bad-version-number-too-large.x b/tools/net/sunrpc/xdrgen/tests/bad-version-number-too-large.x
new file mode 100644
index 000000000000..dd44f6eed564
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/bad-version-number-too-large.x
@@ -0,0 +1,19 @@
+/*
+ * NEGATIVE TEST CASE -- xdrgen must REJECT this specification.
+ *
+ * RFC 5531 encodes program, version, and procedure numbers as unsigned
+ * 32-bit integers (Section 9). This spec gives the version a number one
+ * past the 32-bit maximum, which the front end must reject.
+ *
+ * Expected diagnostic:
+ * version number 4294967296 in program 'BADPROG' exceeds 4294967295
+ *
+ * The tests directory has no automated runner; exercise by hand:
+ * ./xdrgen definitions tests/bad-version-number-too-large.x (must fail)
+ */
+
+program BADPROG {
+ version BADVERS {
+ void BADPROC_NULL(void) = 0;
+ } = 4294967296;
+} = 100000;
diff --git a/tools/net/sunrpc/xdrgen/xdr_ast.py b/tools/net/sunrpc/xdrgen/xdr_ast.py
index ec48506b239a..9dab8bc545b0 100644
--- a/tools/net/sunrpc/xdrgen/xdr_ast.py
+++ b/tools/net/sunrpc/xdrgen/xdr_ast.py
@@ -498,7 +498,7 @@ class _RpcProcedure(_XdrAst):
"""RPC procedure definition"""
name: str
- number: str
+ number: int
argument: _XdrTypeSpecifier
result: _XdrTypeSpecifier
@@ -508,7 +508,7 @@ class _RpcVersion(_XdrAst):
"""RPC version definition"""
name: str
- number: str
+ number: int
procedures: List[_RpcProcedure]
@@ -517,7 +517,7 @@ class _RpcProgram(_XdrAst):
"""RPC program definition"""
name: str
- number: str
+ number: int
versions: List[_RpcVersion]
@@ -933,11 +933,69 @@ def check_duplicate_definitions(root: "Specification") -> None:
_check_rpc_scope_names(definition.value)
+# RFC 5531 (Section 9) encodes program, version, and procedure numbers
+# as unsigned 32-bit integers, so each must fall within [0, 2**32 - 1].
+_RPC_NUMBER_MAX = 2**32 - 1
+
+
+def _check_rpc_number(kind: str, number: int, scope: str, meta) -> None:
+ """Reject one RPC number that is negative or wider than 32 bits."""
+ if number < 0:
+ raise XdrSemanticError(
+ f"negative {kind} number {number} {scope}",
+ meta,
+ )
+ if number > _RPC_NUMBER_MAX:
+ raise XdrSemanticError(
+ f"{kind} number {number} {scope} exceeds {_RPC_NUMBER_MAX}",
+ meta,
+ )
+
+
+def check_rpc_number_range(root: "Specification") -> None:
+ """Reject an out-of-range program, version, or procedure number.
+
+ RFC 5531 assigns only unsigned constants to program, version, and
+ procedure numbers (Section 12.3) and encodes each as an unsigned
+ 32-bit integer (Section 9). RFC 4506 Section 6.2 permits a signed
+ decimal constant for XDR constants in general and sets no ceiling on
+ magnitude, so the grammar accepts an out-of-range value; the range
+ is enforced here instead. The parser retains no per-version or
+ per-procedure source location, so a violation is reported against the
+ program definition.
+ """
+ for definition in root.definitions:
+ program = definition.value
+ if not isinstance(program, _RpcProgram):
+ continue
+ _check_rpc_number(
+ "program",
+ program.number,
+ f"in program '{program.name}'",
+ definition.meta,
+ )
+ for version in program.versions:
+ _check_rpc_number(
+ "version",
+ version.number,
+ f"in program '{program.name}'",
+ definition.meta,
+ )
+ for procedure in version.procedures:
+ _check_rpc_number(
+ "procedure",
+ procedure.number,
+ f"in version '{version.name}'",
+ definition.meta,
+ )
+
+
def transform_parse_tree(parse_tree):
"""Transform productions into an abstract syntax tree"""
ast = transformer.transform(parse_tree)
ast.definitions = _merge_consecutive_passthru(ast.definitions)
check_duplicate_definitions(ast)
+ check_rpc_number_range(ast)
return ast