From: Andrey Rachitskiy Date: Mon, 3 Aug 2026 13:18:00 +0000 Subject: [PATCH] pg_surgery: Fix infinite loop on large tid arrays heap_force_common() tracked the current position in the caller-supplied tid[] using OffsetNumber. That type is a uint16, so when the array held more than 65535 entries the updated index wrapped and the outer loop never reached ntids. A SQL call with a sufficiently large tid[] could then run until cancelled. Fix by tracking the tid[] position with int instead of OffsetNumber. Bug: #19607 Author: Andrey Rachitskiy Reported-by: Yuelin Wang <1217816127@qq.com> Discussion: https://postgr.es/m/19607-2f256a66481c514b@postgresql.org Backpatch-through: 14 --- diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c index 181b7d1e210..51f3f3c49eb 100644 --- a/contrib/pg_surgery/heap_surgery.c +++ b/contrib/pg_surgery/heap_surgery.c @@ -44,7 +44,7 @@ static Datum heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt); static void sanity_check_tid_array(ArrayType *ta, int *ntids); static BlockNumber find_tids_one_page(ItemPointer tids, int ntids, - OffsetNumber *next_start_ptr); + int *next_start_ptr); /*------------------------------------------------------------------------- * heap_force_kill() @@ -91,7 +91,7 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt) int ntids, nblocks; Relation rel; - OffsetNumber curr_start_ptr, + int curr_start_ptr, next_start_ptr; bool include_this_tid[MaxHeapTuplesPerPage]; @@ -413,7 +413,7 @@ sanity_check_tid_array(ArrayType *ta, int *ntids) * ------------------------------------------------------------------------ */ static BlockNumber -find_tids_one_page(ItemPointer tids, int ntids, OffsetNumber *next_start_ptr) +find_tids_one_page(ItemPointer tids, int ntids, int *next_start_ptr) { int i; BlockNumber prev_blkno,