From 706d0421ae23119382bbe41bf38570b1b4cb6edf Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 4 Dec 2025 15:31:39 +0200
Subject: [PATCH v28 6/6] Add runtime checks for bogus multixact offsets

These are not directly related to 64 bit offsets, but makes sense I
think
---
 src/backend/access/transam/multixact.c | 33 ++++++++++++++++----------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index dffa0c8e7d4..dc9c4257a98 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1154,6 +1154,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 	int			slotno;
 	MultiXactOffset *offptr;
 	MultiXactOffset offset;
+	MultiXactOffset nextMXOffset;
 	int			length;
 	MultiXactId oldestMXact;
 	MultiXactId nextMXact;
@@ -1245,12 +1246,14 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 	offptr += entryno;
 	offset = *offptr;
 
-	Assert(offset != 0);
+	if (offset == 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATA_CORRUPTED),
+				 errmsg("MultiXact %u has invalid offset", multi)));
 
 	/* read next multi's offset */
 	{
 		MultiXactId tmpMXact;
-		MultiXactOffset nextMXOffset;
 
 		/* handle wraparound if needed */
 		tmpMXact = multi + 1;
@@ -1284,21 +1287,27 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 		offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
 		offptr += entryno;
 		nextMXOffset = *offptr;
-
-		if (nextMXOffset == 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_DATA_CORRUPTED),
-					 errmsg("MultiXact %u has invalid next offset",
-							multi)));
-
-		length = nextMXOffset - offset;
 	}
 
 	LWLockRelease(lock);
 	lock = NULL;
 
-	/* A multixid with zero members should not happen */
-	Assert(length > 0);
+	/* Sanity check the next offset */
+	if (nextMXOffset == 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATA_CORRUPTED),
+				 errmsg("MultiXact %u has invalid next offset", multi)));
+	if (nextMXOffset < offset)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATA_CORRUPTED),
+				 errmsg("MultiXact %u has offset (%" PRIu64") greater than its next offset  (%" PRIu64")",
+						multi, offset, nextMXOffset)));
+	if (nextMXOffset - offset > INT32_MAX)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATA_CORRUPTED),
+				 errmsg("MultiXact %u has too many members (%" PRIu64 ")",
+						multi, nextMXOffset - offset)));
+	length = nextMXOffset - offset;
 
 	/* read the members */
 	ptr = (MultiXactMember *) palloc(length * sizeof(MultiXactMember));
-- 
2.47.3

