mirror of
https://github.com/postgres/postgres.git
synced 2025-12-13 14:22:43 +03:00
Add runtime checks for bogus multixact offsets
It's not far-fetched that we'd try to read a multixid with an invalid offset in case of bugs or corruption. Or if you call pg_get_multixact_members() after a crash that left behind invalid but unused multixids. Better to get a somewhat descriptive error message if that happens. Discussion: https://www.postgresql.org/message-id/3624730d-6dae-42bf-9458-76c4c965fb27@iki.fi
This commit is contained in:
@@ -1153,6 +1153,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
|
||||
int slotno;
|
||||
MultiXactOffset *offptr;
|
||||
MultiXactOffset offset;
|
||||
MultiXactOffset nextMXOffset;
|
||||
int length;
|
||||
MultiXactId oldestMXact;
|
||||
MultiXactId nextMXact;
|
||||
@@ -1244,12 +1245,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;
|
||||
@@ -1283,21 +1286,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));
|
||||
|
||||
Reference in New Issue
Block a user