From b4c62d4d32683341b3a344936e8ac8ad958d9f7b Mon Sep 17 00:00:00 2001 From: spoondla 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)