From f0a59c18ecb068bbf417c9a8c8cbbcc37460dd3f Mon Sep 17 00:00:00 2001
From: Sunil Seetharama <sunil.s@broadcom.com>
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

