diff --git a/pdf.c b/pdf.c
index 40773733bf4cd8d4400ceaaf8cd3139d09973081..dc689d1f78a73a4fbbeeef9acdb353a2aba10300 100644
--- a/pdf.c
+++ b/pdf.c
@@ -4706,6 +4706,22 @@ p_xrefdata__m(HAllocator *mm__, const Dict *dict)
 
 
 
+/*
+ * Validate that the number of objects in an object stream's index matches the
+ * number that are actually present.
+ *
+ * p = (idx, objs)
+ */
+bool
+validate_ostm(HParseResult *p, void *u)
+{
+	HCountedArray *idx = H_FIELD_SEQ(0);
+	HCountedArray *objs = H_FIELD_SEQ(1);
+
+	return (idx->used == objs->used);
+	// XXX also consistency-check object positions against idx and /First
+}
+
 HParsedToken *
 act_ostm(const HParseResult *p, void *u)
 {
@@ -4749,18 +4765,17 @@ p_objstm__m(HAllocator *mm__, const Dict *dict)
 
 	HParser *wel_ws = h_sequence__m(mm__, p_wel, p_ws, NULL);
 	HParser *idx = p_sepBy_n__m(mm__, p_npair, wel_ws, N);
-
-	HParser *p_ostm = h_sequence__m(mm__, p_ws, idx, p_objs, p_ws, NULL);
+	HParser *ostm = h_sequence__m(mm__, p_ws, idx, p_objs, p_ws, NULL);
+		// XXX leading and trailing ws OK?
 		// XXX plain indirect references not allowed in object streams
 		// ISO 32000-2:2020, 7.5.7 "Object streams":
 		// > An object in an object stream shall not consist solely of
 		// > an object reference.
-	HParser *ostm_p = h_action__m(mm__, p_ostm, act_ostm, (void *)v);
 
-	return ostm_p;
-		// XXX leading and trailing ws OK?
+	ostm = h_attr_bool__m(mm__, ostm, validate_ostm, NULL);
+	ostm = h_action__m(mm__, ostm, act_ostm, (void *)v);
 
-	// XXX consistency-check against /First, idx, /N
+	return ostm;
 }
 
 /*