public inbox for [email protected]  
help / color / mirror / Atom feed
From: Michael Paquier <[email protected]>
To: Ashutosh Bapat <[email protected]>
Cc: Andres Freund <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: GetBufferDescriptor() being called for local buffers from MarkBufferDirtyHint()
Date: Wed, 10 Jun 2026 12:40:38 +0900
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAExHW5uzRMYVZsXXS3HXXT0fG_sNrpUhUqwP4NorhaCqH9JDhA@mail.gmail.com>
References: <CAExHW5uzRMYVZsXXS3HXXT0fG_sNrpUhUqwP4NorhaCqH9JDhA@mail.gmail.com>

On Sat, Jun 06, 2026 at 01:37:42PM +0530, Ashutosh Bapat wrote:
> 82467f627bd478569de04f4a3f1993098e80c812 added MarkBufferDirtyHint()
> which invokes GetBufferDescriptor() even for local buffers for which
> id < 0. Since GetBufferDescriptor() declares id as uint32, -1 is
> converted to a very large int32 value which is way larger than
> NBuffers. Thus GetBufferDescriptor() may be returning something from
> the BufferBlocks which probably has enough memory to accommodate that
> memory access. But it's a bogus BufferDesc nevertheless. We are not
> seeing any problem with this right now since MarkBufferDirtyHint()
> uses the BufferDesc only when it's a shared buffer. Right fix is to
> let that function handle local buffers first and then call
> GetBufferDescriptor() as in the attached patch.

@@ -5831,8 +5831,6 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
 {
     BufferDesc *bufHdr;
 
-    bufHdr = GetBufferDescriptor(buffer - 1);
-
     if (!BufferIsValid(buffer))
         elog(ERROR, "bad buffer ID: %d", buffer);
 
@@ -5842,6 +5840,8 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
         return;
     }
 
+    bufHdr = GetBufferDescriptor(buffer - 1);

Yep, that's clearly wrong.  We are lucky that it does not blow up
today but that's a ticking bomb.  Even with that in mind, the result
leads to a non-defined behavior.

-    return &(BufferDescriptors[id]).bufferdesc;
+    BufferDesc *bdesc = &(BufferDescriptors[id]).bufferdesc;
+
+    Assert(bdesc->buf_id == id);
+
+    return bdesc; 
[...]
-        BufferDesc *buf = GetBufferDescriptor(i);
+        /* GetBufferDescriptor() expects buf_id to be set in the descriptor. */
+        BufferDesc *buf = &(BufferDescriptors[i]).bufferdesc;

I am not convinced by these two.  For the first one, the assertion is
a bound check in disguise, which could also use NBuffers as of an (id
< NBuffers).  With the inlining we care about the performance.  This
also forces the second change in ShmemInit(), which makes even less
sense once we think about the first assertion.

Will fix the first issue on HEAD, that's wrong.  Thanks for the
report.
--
Michael


Attachments:

  [application/pgp-signature] signature.asc (833B, 2-signature.asc)
  download

view thread (5+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected]
  Subject: Re: GetBufferDescriptor() being called for local buffers from MarkBufferDirtyHint()
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox