From f0a59c18ecb068bbf417c9a8c8cbbcc37460dd3f Mon Sep 17 00:00:00 2001 From: Sunil Seetharama Date: Fri, 17 Oct 2025 10:51:42 +0530 Subject: [PATCH] BRIN: Prevent the heapblk overflow during index summarization on very large tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, `heapBlk` was defined as an unsigned 32-bit integer. When incremented by `pagesPerRange` on very large tables, it could wrap around, causing the condition `heapBlk < nblocks` to remain true indefinitely — resulting in an infinite loop. This could cause the PostgreSQL backend to hang, consuming 100% CPU indefinitely and preventing operations from completing on large tables. The solution is straightforward — the data type of `heapBlk` has been changed from a 32-bit integer to a 64-bit `BlockNumber` (int64), ensuring it can safely handle extremely large tables without risk of overflow. This was explained very nicely by Tomas Vondra[1] and below two solutions were suggested. i) Change to int64 ii) Tracking the prevHeapBlk Among these two I feel using solution #1 would be more feasible(similar to previously used solution #2), though other solution also works. Reference: [1] https://www.postgresql.org/message-id/b8a4e04c-c091-056c-a379-11d35c7b2d8d%40enterprisedb.com [2] https://github.com/postgres/postgres/commit/4bc6fb57f774ea18187fd8565aad9994160bfc17 --- src/backend/access/brin/brin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 7ff7467e462..6a273e9fc39 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -573,7 +573,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) Relation heapRel; BrinOpaque *opaque; BlockNumber nblocks; - BlockNumber heapBlk; + int64 heapBlk; int64 totalpages = 0; FmgrInfo *consistentFn; MemoryContext oldcxt; @@ -749,7 +749,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) MemoryContextReset(perRangeCxt); - tup = brinGetTupleForHeapBlock(opaque->bo_rmAccess, heapBlk, &buf, + tup = brinGetTupleForHeapBlock(opaque->bo_rmAccess, (BlockNumber )heapBlk, &buf, &off, &size, BUFFER_LOCK_SHARE); if (tup) { -- 2.50.1