From 20965aa3c94647c9045538b47aa56e3d8b4d42dc Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Fri, 3 Jul 2026 00:39:15 +0000
Subject: [PATCH v3] Make buffer descriptor accessors take signed int

GetBufferDescriptor() and GetLocalBufferDescriptor() took a uint32 buffer
index, but every real caller derives the index from a Buffer -- buffer - 1
for shared buffers, -buffer - 1 for local buffers -- i.e. a signed value.
Passing a negative index (as MarkBufferDirtyHint() briefly did for local
buffers, since fixed) silently wrapped to a large uint32 and produced a bogus
descriptor pointer instead of failing.

Change both accessors to take a signed int, and add a bounds assertion to
GetBufferDescriptor() to catch out-of-range shared-buffer indexes.  NBuffers
is validated as a GUC and fixed before shared memory is initialized, so the
assertion holds everywhere the accessor is used, including the descriptor
initialization loop in BufferManagerShmemInit().

GetLocalBufferDescriptor() gets the signed parameter but no NLocBuffer
assertion: NLocBuffer is only established while InitLocalBuffers() runs, so a
bound check there would be unreliable, and establishing NLocBuffer earlier is
unsafe because the local buffer hash table allocation can still fail with an
error after it is set.

ClockSweepTick() continues to return uint32; its result is always a modulo of
NBuffers and is therefore in range when passed to GetBufferDescriptor().

Discussion: https://postgr.es/m/CAExHW5uzRMYVZsXXS3HXXT0fG_sNrpUhUqwP4NorhaCqH9JDhA@mail.gmail.com
---
 src/include/storage/buf_internals.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 89615a254a3..2a1ffcc6c5c 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -419,13 +419,15 @@ 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)
 {
 	return &LocalBufferDescriptors[id];
 }
-- 
2.43.0

