0001-Fix-off-by-one-stack-buffer-overflow-in-pg_surgery.patch
application/octet-stream
Filename: 0001-Fix-off-by-one-stack-buffer-overflow-in-pg_surgery.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Fix off-by-one stack buffer overflow in pg_surgery Issue: heap_force_common() declared include_this_tid[] with MaxHeapTuplesPerPage slots and indexed it directly with a 1-based OffsetNumber, so an input TID whose offset number equals MaxHeapTuplesPerPage wrote one byte past the end of the stack array and this woulod cause a seg fault and crash postgres
| File | + | − |
|---|---|---|
| contrib/pg_surgery/heap_surgery.c | 6 | 3 |
From b4c62d4d32683341b3a344936e8ac8ad958d9f7b Mon Sep 17 00:00:00 2001
From: spoondla <s_poondla@apple.com>
Date: Wed, 3 Jun 2026 15:17:00 -0700
Subject: [PATCH] Fix off-by-one stack buffer overflow in pg_surgery Issue:
heap_force_common() declared include_this_tid[] with MaxHeapTuplesPerPage
slots and indexed it directly with a 1-based OffsetNumber, so an input TID
whose offset number equals MaxHeapTuplesPerPage wrote one byte past the end
of the stack array and this woulod cause a seg fault and crash postgres
Fix:
Updated the size of include_this_tid[] as MaxHeapTuplesPerPage + 1 so every legal
1-based offset has a slot, and reject offno > MaxHeapTuplesPerPage in
the per-TID validation so a corrupted page header that reports an
impossibly large maxoffset cannot reach the array either.
---
contrib/pg_surgery/heap_surgery.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c
index ae4e7c0136c..19169131815 100644
--- a/contrib/pg_surgery/heap_surgery.c
+++ b/contrib/pg_surgery/heap_surgery.c
@@ -92,7 +92,8 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
Relation rel;
OffsetNumber curr_start_ptr,
next_start_ptr;
- bool include_this_tid[MaxHeapTuplesPerPage];
+ /* Sized +1 because OffsetNumbers are 1-based and can reach MaxHeapTuplesPerPage. */
+ bool include_this_tid[MaxHeapTuplesPerPage + 1];
if (RecoveryInProgress())
ereport(ERROR,
@@ -193,7 +194,9 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
ItemId itemid;
/* Check whether the offset number is valid. */
- if (offno == InvalidOffsetNumber || offno > maxoffset)
+ if (offno == InvalidOffsetNumber ||
+ offno > maxoffset ||
+ offno > MaxHeapTuplesPerPage)
{
ereport(NOTICE,
errmsg("skipping tid (%u, %u) for relation \"%s\" because the item number is out of range",
@@ -228,7 +231,7 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
}
/* Mark it for processing. */
- Assert(offno < MaxHeapTuplesPerPage);
+ Assert(offno <= MaxHeapTuplesPerPage);
include_this_tid[offno] = true;
}
--
2.39.5 (Apple Git-154)