From dd26589007f7532415816c5ef4ca4dd4c6d54a36 Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Wed, 1 Jul 2026 08:40:48 +0000
Subject: [PATCH v2] Make buffer descriptor accessors take signed int

GetBufferDescriptor() and GetLocalBufferDescriptor() took a uint32 buffer
index.  A Buffer is a signed int and callers routinely pass "buffer - 1"
or "-buffer - 1", so a malformed Buffer could silently wrap into a huge
positive index.  Switch the parameter to int and add bounds assertions
(0 <= id < NBuffers / NLocBuffer) so such mistakes are caught.

The new assertion in GetLocalBufferDescriptor() exposed that
InitLocalBuffers() initializes the local buffer descriptors via
GetLocalBufferDescriptor() before publishing NLocBuffer, so the bounds
check saw NLocBuffer == 0.  Establish NLocBuffer before the initialization
loop, mirroring shared buffers where NBuffers is set before
BufferManagerShmemInit() initializes the descriptors; whether local buffers
are ready for use is tracked separately via LocalBufHash.

Discussion: https://postgr.es/m/CAExHW5uzRMYVZsXXS3HXXT0fG_sNrpUhUqwP4NorhaCqH9JDhA@mail.gmail.com
---
 src/backend/storage/buffer/localbuf.c | 8 ++++----
 src/include/storage/buf_internals.h   | 8 ++++++--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 4870c8e13d0..06bb2b65318 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -42,7 +42,7 @@ typedef struct
 #define LocalBufHdrGetBlock(bufHdr) \
 	LocalBufferBlockPointers[-((bufHdr)->buf_id + 2)]
 
-int			NLocBuffer = 0;		/* until buffers are initialized */
+int			NLocBuffer = 0;		/* until buffers are allocated */
 
 BufferDesc *LocalBufferDescriptors = NULL;
 Block	   *LocalBufferBlockPointers = NULL;
@@ -777,6 +777,9 @@ InitLocalBuffers(void)
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of memory")));
 
+	/* Record the local buffer count now that the arrays are allocated. */
+	NLocBuffer = nbufs;
+
 	nextFreeLocalBufId = 0;
 
 	/* initialize fields that need to start off nonzero */
@@ -813,9 +816,6 @@ InitLocalBuffers(void)
 
 	if (!LocalBufHash)
 		elog(ERROR, "could not initialize local buffer hash table");
-
-	/* Initialization done, mark buffers allocated */
-	NLocBuffer = nbufs;
 }
 
 /*
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 89615a254a3..7b13ec0dc74 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -419,14 +419,18 @@ extern PGDLLIMPORT BufferDesc *LocalBufferDescriptors;
 
 
 static inline BufferDesc *
-GetBufferDescriptor(uint32 id)
+GetBufferDescriptor(int id)
 {
+	Assert(id >= 0 && id < NBuffers);
+
 	return &(BufferDescriptors[id]).bufferdesc;
 }
 
 static inline BufferDesc *
-GetLocalBufferDescriptor(uint32 id)
+GetLocalBufferDescriptor(int id)
 {
+	Assert(id >= 0 && id < NLocBuffer);
+
 	return &LocalBufferDescriptors[id];
 }
 
-- 
2.43.0

