diff --git a/pdf.c b/pdf.c
index 5fea3229c1a5a68e5aaa9646a80fe8c15f81f720..40773733bf4cd8d4400ceaaf8cd3139d09973081 100644
--- a/pdf.c
+++ b/pdf.c
@@ -977,6 +977,21 @@ act_xrstment(const HParseResult *p, void *u)
 	return H_MAKE(XREntry, xr);
 }
 
+/*
+ * Validate that the declared number of entries in a cross-reference
+ * subsection matches the number that was actually parsed.
+ *
+ * p = ((nat nat) (xrent ...))
+ */
+bool
+validate_xrsub(HParseResult *p, void *u)
+{
+	uint64_t n = H_FIELD_UINT(0, 1);
+	HCountedArray *seq = H_FIELD_SEQ(1);
+
+	return (seq->used == n);
+}
+
 #define act_xrefs h_act_last
 
 /*
@@ -2477,7 +2492,7 @@ init_parser(struct Env *aux)
 	    xreol,
 	    VIOL(SEQ(h_many1(wchar)), "Nonconformant WS at end of xref entry (severity=1)")))));
 	H_RULE(xrhead,	SEQ(nat, IGN(sp), nat, nl));
-	H_RULE(xrsub,	SEQ(xrhead, h_many(xrent)));
+	H_VRULE(xrsub,	SEQ(xrhead, h_many(xrent)));
 	H_ARULE(xrefs,	SEQ(KW("xref"), nl, h_many(xrsub)));
 
 	/* cross-reference streams */