public inbox for [email protected]
help / color / mirror / Atom feedBUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
10+ messages / 4 participants
[nested] [flat]
* BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
@ 2026-06-04 14:35 PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: PG Bug reporting form @ 2026-06-04 14:35 UTC (permalink / raw)
To: [email protected]; +Cc: [email protected]
The following bug has been logged on the website:
Bug reference: 19508
Logged by: Nikita Kalinin
Email address: [email protected]
PostgreSQL version: 19beta1
Operating system: Fedora 44
Description:
Hello,
It appears that pg_buffercache_pages() trusts a caller-supplied record
descriptor without verifying that the declared column types match the actual
values returned by the function.
The crash is reproducible on the current master branch with a fresh cluster
after installing the extension:
CREATE EXTENSION pg_buffercache;
SELECT *
FROM pg_buffercache_pages() AS p(
bufferid integer,
relfilenode oid,
reltablespace oid,
reldatabase oid,
relforknumber smallint,
relblocknumber bigint,
isdirty text,
usagecount smallint
)
LIMIT 1;
postgres=# select version();
version
-------------------------------------------------------------------------------------------------------------
PostgreSQL 19beta1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 16.1.1
20260515 (Red Hat 16.1.1-2), 64-bit
(1 row)
The only difference from the types documented for pg_buffercache_pages() is
that isdirty is declared as text instead of boolean.
git blame points to the following commit:
commit 257c8231bf97a77378f6fedb826b1243f0a41612 (HEAD)
Author: Heikki Linnakangas <[email protected]>
Date: Tue Apr 7 16:04:48 2026 +0300
Modernize and optimize pg_buffercache_pages()
Backtrace:
#0 0x00000000004b2565 in VARATT_CAN_MAKE_SHORT (PTR=<optimized out>)
at ../../../../src/include/varatt.h:419
#1 heap_compute_data_size (tupleDesc=tupleDesc@entry=0x3e5ba110,
values=values@entry=0x7ffd0dc219c0, isnull=isnull@entry=0x7ffd0dc219b4)
at heaptuple.c:239
#2 0x00000000004b3bff in heap_form_minimal_tuple
(tupleDescriptor=0x3e5ba110,
values=values@entry=0x7ffd0dc219c0, isnull=isnull@entry=0x7ffd0dc219b4,
extra=extra@entry=0)
at heaptuple.c:1434
#3 0x0000000000a6fa09 in tuplestore_putvalues (state=0x3e5cc0d8,
tdesc=<optimized out>,
values=values@entry=0x7ffd0dc219c0, isnull=isnull@entry=0x7ffd0dc219b4)
at tuplestore.c:791
#4 0x00007f180fa0447e in pg_buffercache_pages (fcinfo=<optimized out>)
at pg_buffercache_pages.c:202
#5 0x00000000006b7e35 in ExecMakeTableFunctionResult (setexpr=0x3e5b9e98,
econtext=0x3e5b9d38,
argContext=<optimized out>, expectedDesc=0x3e5ba110, randomAccess=false)
at execSRF.c:235
#6 0x00000000006ccc57 in FunctionNext (node=0x3e5b9b28) at
nodeFunctionscan.c:95
#7 0x00000000006daf22 in ExecProcNode (node=0x3e5b9b28)
at ../../../src/include/executor/executor.h:327
#8 ExecLimit (pstate=0x3e5b97b8) at nodeLimit.c:95
#9 0x00000000006ac39a in ExecProcNode (node=0x3e5b97b8)
at ../../../src/include/executor/executor.h:327
#10 ExecutePlan (queryDesc=0x3e5d7d80, operation=CMD_SELECT,
sendTuples=true, numberTuples=0,
direction=<optimized out>, dest=0x3e5e11f8) at execMain.c:1736
#11 standard_ExecutorRun (queryDesc=0x3e5d7d80, direction=<optimized out>,
count=0)
at execMain.c:377
#12 0x00000000008c61d8 in PortalRunSelect (portal=portal@entry=0x3e52f130,
forward=forward@entry=true, count=0, count@entry=9223372036854775807,
dest=dest@entry=0x3e5e11f8) at pquery.c:917
#13 0x00000000008c78be in PortalRun (portal=portal@entry=0x3e52f130,
count=count@entry=9223372036854775807, isTopLevel=isTopLevel@entry=true,
dest=dest@entry=0x3e5e11f8, altdest=altdest@entry=0x3e5e11f8,
qc=qc@entry=0x7ffd0dc21e20)
at pquery.c:761
#14 0x00000000008c3548 in exec_simple_query (
query_string=0x3e48b800 "SELECT *\nFROM pg_buffercache_pages() AS p(\n
bufferid integer,\n relfilenode oid,\n reltablespace oid,\n reldatabase
oid,\n relforknumber smallint,\n relblocknumber bigint,\n isdirty text,\n
usagecoun"...) at postgres.c:1290
#15 0x00000000008c5021 in PostgresMain (dbname=<optimized out>,
username=<optimized out>)
at postgres.c:4856
#16 0x00000000008bf01d in BackendMain (startup_data=<optimized out>,
startup_data_len=<optimized out>) at backend_startup.c:124
#17 0x00000000007fefae in postmaster_child_launch (child_type=<optimized
out>, child_slot=1,
startup_data=startup_data@entry=0x7ffd0dc22270,
startup_data_len=startup_data_len@entry=24,
client_sock=client_sock@entry=0x7ffd0dc22290) at launch_backend.c:268
#18 0x00000000008029b6 in BackendStartup (client_sock=0x7ffd0dc22290) at
postmaster.c:3627
#19 ServerLoop () at postmaster.c:1728
#20 0x0000000000804479 in PostmasterMain (argc=argc@entry=3,
argv=argv@entry=0x3e434fe0)
at postmaster.c:1415
#21 0x00000000004a1c18 in main (argc=3, argv=0x3e434fe0) at main.c:231
For comparison, the same query executed on REL_18_STABLE is rejected with a
regular error:
ERROR: function return row and query-specified return row do not match
DETAIL: Returned type boolean at ordinal position 7, but query expects
text.
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
@ 2026-06-05 03:18 ` Fujii Masao <[email protected]>
2026-06-05 03:42 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
2026-06-05 15:29 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ashutosh Sharma <[email protected]>
0 siblings, 2 replies; 10+ messages in thread
From: Fujii Masao @ 2026-06-05 03:18 UTC (permalink / raw)
To: [email protected]; [email protected]
On Fri, Jun 5, 2026 at 12:49 AM PG Bug reporting form
<[email protected]> wrote:
>
> The following bug has been logged on the website:
>
> Bug reference: 19508
> Logged by: Nikita Kalinin
> Email address: [email protected]
> PostgreSQL version: 19beta1
> Operating system: Fedora 44
> Description:
>
> Hello,
>
> It appears that pg_buffercache_pages() trusts a caller-supplied record
> descriptor without verifying that the declared column types match the actual
> values returned by the function.
>
> The crash is reproducible on the current master branch with a fresh cluster
> after installing the extension:
Thanks for the report! I could reproduce this as well.
> git blame points to the following commit:
>
> commit 257c8231bf97a77378f6fedb826b1243f0a41612 (HEAD)
> Author: Heikki Linnakangas <[email protected]>
> Date: Tue Apr 7 16:04:48 2026 +0300
>
> Modernize and optimize pg_buffercache_pages()
Commit 257c8231bf9 changed pg_buffercache_pages() to materialize rows directly
into a tuplestore. As a result, the function started using the caller-supplied
RECORD descriptor as rsinfo->setDesc, so a mismatched column definition list
could cause tuplestore_putvalues() to interpret returned Datums with incorrect
types.
Before that change, pg_buffercache_pages() exposed its actual tuple descriptor
to the executor, allowing the executor's existing rowtype checks to reject
incompatible definitions with a normal error.
The attached patch restores that behavior while keeping the materialized-SRF
implementation. Thoughts?
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v1-0001-pg_buffercache-restore-rowtype-verification-in-pg.patch (5.4K, 2-v1-0001-pg_buffercache-restore-rowtype-verification-in-pg.patch)
download | inline diff:
From 55320441a6862b4ee17b8af81be17a2783c021e8 Mon Sep 17 00:00:00 2001
From: "masao.fujii" <[email protected]’s-MacBook-Pro>
Date: Fri, 5 Jun 2026 10:37:12 +0900
Subject: [PATCH v1] pg_buffercache: restore rowtype verification in
pg_buffercache_pages()
Commit 257c8231bf9 changed pg_buffercache_pages() to materialize its output
directly into a tuplestore. As a result, the function ended up trusting
a caller-supplied RECORD descriptors. That could lead to crashes
if the supplied row definition did not match the actual returned values,
for example by passing bool Datums to tuplestore_putvalues() with
an incompatible descriptor.
Fix this by constructing the correct tuple descriptor for
pg_buffercache_pages() and assigning it to
rsinfo->setDesc after InitMaterializedSRF(). This restores the executor's
tupledesc_match() verification, so incompatible caller-supplied
row definitions are rejected with an error, as before commit 257c8231bf9.
---
.../expected/pg_buffercache.out | 8 +++
contrib/pg_buffercache/pg_buffercache_pages.c | 51 +++++++++++++++++++
contrib/pg_buffercache/sql/pg_buffercache.sql | 6 +++
3 files changed, 65 insertions(+)
diff --git a/contrib/pg_buffercache/expected/pg_buffercache.out b/contrib/pg_buffercache/expected/pg_buffercache.out
index 886dea770f6..c52a8491ff9 100644
--- a/contrib/pg_buffercache/expected/pg_buffercache.out
+++ b/contrib/pg_buffercache/expected/pg_buffercache.out
@@ -73,6 +73,14 @@ SELECT count(*) > 0 FROM pg_buffercache_usage_counts();
t
(1 row)
+SELECT *
+FROM pg_buffercache_pages() AS p
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+ relforknumber smallint, relblocknumber bigint, isdirty text,
+ usagecount smallint)
+LIMIT 1;
+ERROR: function return row and query-specified return row do not match
+DETAIL: Returned type boolean at ordinal position 7, but query expects text.
RESET role;
------
---- Test pg_buffercache_evict* and pg_buffercache_mark_dirty* functions
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index bf2e6c97220..34c9b939313 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -59,6 +59,8 @@ typedef struct
BufferCacheOsPagesRec *record;
} BufferCacheOsPagesContext;
+static TupleDesc build_buffercache_pages_tupledesc(int natts);
+
/*
* Function returning data from the shared buffer cache - buffer number,
@@ -86,6 +88,8 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc expected_tupledesc;
+ TupleDesc actual_tupledesc;
+ MemoryContext oldcontext;
int i;
/*
@@ -105,6 +109,21 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
InitMaterializedSRF(fcinfo, 0);
+ oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
+ actual_tupledesc = build_buffercache_pages_tupledesc(expected_tupledesc->natts);
+ MemoryContextSwitchTo(oldcontext);
+
+ /*
+ * Override the caller-supplied descriptor with the tuple descriptor that
+ * matches the values we actually return, so executor-side
+ * tupledesc_match() can verify the caller's row definition.
+ *
+ * Do not free the previous rsinfo->setDesc here: for RECORD results it
+ * can alias rsinfo->expectedDesc, which the executor still needs to
+ * reference.
+ */
+ rsinfo->setDesc = actual_tupledesc;
+
/*
* Scan through all the buffers, adding one row for each of the buffers to
* the tuplestore.
@@ -205,6 +224,38 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
return (Datum) 0;
}
+static TupleDesc
+build_buffercache_pages_tupledesc(int natts)
+{
+ TupleDesc tupledesc;
+
+ tupledesc = CreateTemplateTupleDesc(natts);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relforknumber",
+ INT2OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 6, "relblocknumber",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 7, "isdirty",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usage_count",
+ INT2OID, -1, 0);
+
+ if (natts == NUM_BUFFERCACHE_PAGES_ELEM)
+ TupleDescInitEntry(tupledesc, (AttrNumber) 9, "pinning_backends",
+ INT4OID, -1, 0);
+
+ TupleDescFinalize(tupledesc);
+
+ return BlessTupleDesc(tupledesc);
+}
+
/*
* Inquire about OS pages mappings for shared buffers, with NUMA information,
* optionally.
diff --git a/contrib/pg_buffercache/sql/pg_buffercache.sql b/contrib/pg_buffercache/sql/pg_buffercache.sql
index 127d604905c..be89b5f5a3a 100644
--- a/contrib/pg_buffercache/sql/pg_buffercache.sql
+++ b/contrib/pg_buffercache/sql/pg_buffercache.sql
@@ -34,6 +34,12 @@ SELECT count(*) > 0 FROM pg_buffercache;
SELECT count(*) > 0 FROM pg_buffercache_os_pages;
SELECT buffers_used + buffers_unused > 0 FROM pg_buffercache_summary();
SELECT count(*) > 0 FROM pg_buffercache_usage_counts();
+SELECT *
+FROM pg_buffercache_pages() AS p
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+ relforknumber smallint, relblocknumber bigint, isdirty text,
+ usagecount smallint)
+LIMIT 1;
RESET role;
--
2.53.0
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
@ 2026-06-05 03:42 ` Ayush Tiwari <[email protected]>
2026-06-05 07:58 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
1 sibling, 1 reply; 10+ messages in thread
From: Ayush Tiwari @ 2026-06-05 03:42 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: [email protected]; [email protected]
Hi,
On Fri, 5 Jun 2026 at 08:49, Fujii Masao <[email protected]> wrote:
>
> Commit 257c8231bf9 changed pg_buffercache_pages() to materialize rows
> directly
> into a tuplestore. As a result, the function started using the
> caller-supplied
> RECORD descriptor as rsinfo->setDesc, so a mismatched column definition
> list
> could cause tuplestore_putvalues() to interpret returned Datums with
> incorrect
> types.
>
> Before that change, pg_buffercache_pages() exposed its actual tuple
> descriptor
> to the executor, allowing the executor's existing rowtype checks to reject
> incompatible definitions with a normal error.
>
> The attached patch restores that behavior while keeping the
> materialized-SRF
> implementation. Thoughts?
>
Thanks for the patch, Fujii-san!
I was looking into the bug last night, and the approach looks right to me.
This still means InitMaterializedSRF() briefly creates the caller-derived
descriptor before rsinfo->setDesc is replaced. That seems acceptable here:
the descriptor lives only in the per-query context, and avoiding a local
copy of InitMaterializedSRF() keeps the fix much smaller and less fragile.
One small nit: build_buffercache_pages_tupledesc() names attribute 8
"usage_count", while the existing pg_buffercache view and the test use
"usagecount". This probably does not affect the tupledesc_match() check,
but I think it would be better to keep the existing spelling for
consistency.
Regards,
Ayush
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 03:42 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
@ 2026-06-05 07:58 ` Fujii Masao <[email protected]>
2026-06-05 08:47 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Fujii Masao @ 2026-06-05 07:58 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; +Cc: [email protected]; [email protected]
On Fri, Jun 5, 2026 at 12:42 PM Ayush Tiwari
<[email protected]> wrote:
> One small nit: build_buffercache_pages_tupledesc() names attribute 8
> "usage_count", while the existing pg_buffercache view and the test use
> "usagecount". This probably does not affect the tupledesc_match() check,
> but I think it would be better to keep the existing spelling for
> consistency.
Agreed. I've fixed that and attached an updated version of the patch.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v2-0001-pg_buffercache-restore-rowtype-verification-in-pg.patch (5.6K, 2-v2-0001-pg_buffercache-restore-rowtype-verification-in-pg.patch)
download | inline diff:
From 9881fc247daab96549d7aaaf60243227b3274059 Mon Sep 17 00:00:00 2001
From: "masao.fujii" <[email protected]’s-MacBook-Pro>
Date: Fri, 5 Jun 2026 10:37:12 +0900
Subject: [PATCH v2] pg_buffercache: restore rowtype verification in
pg_buffercache_pages()
Commit 257c8231bf9 changed pg_buffercache_pages() to materialize its output
directly into a tuplestore. As a result, the function ended up trusting
a caller-supplied RECORD descriptors. That could lead to crashes
if the supplied row definition did not match the actual returned values,
for example by passing bool Datums to tuplestore_putvalues() with
an incompatible descriptor.
Fix this by constructing the correct tuple descriptor for
pg_buffercache_pages() and assigning it to
rsinfo->setDesc after InitMaterializedSRF(). This restores the executor's
tupledesc_match() verification, so incompatible caller-supplied
row definitions are rejected with an error, as before commit 257c8231bf9.
Bug: #19508
Reported-by: Nikita Kalinin <[email protected]>
Author: Fujii Masao <[email protected]>
Reviewed-by: Ayush Tiwari <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
.../expected/pg_buffercache.out | 8 +++
contrib/pg_buffercache/pg_buffercache_pages.c | 51 +++++++++++++++++++
contrib/pg_buffercache/sql/pg_buffercache.sql | 6 +++
3 files changed, 65 insertions(+)
diff --git a/contrib/pg_buffercache/expected/pg_buffercache.out b/contrib/pg_buffercache/expected/pg_buffercache.out
index 886dea770f6..c52a8491ff9 100644
--- a/contrib/pg_buffercache/expected/pg_buffercache.out
+++ b/contrib/pg_buffercache/expected/pg_buffercache.out
@@ -73,6 +73,14 @@ SELECT count(*) > 0 FROM pg_buffercache_usage_counts();
t
(1 row)
+SELECT *
+FROM pg_buffercache_pages() AS p
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+ relforknumber smallint, relblocknumber bigint, isdirty text,
+ usagecount smallint)
+LIMIT 1;
+ERROR: function return row and query-specified return row do not match
+DETAIL: Returned type boolean at ordinal position 7, but query expects text.
RESET role;
------
---- Test pg_buffercache_evict* and pg_buffercache_mark_dirty* functions
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index bf2e6c97220..510455998aa 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -59,6 +59,8 @@ typedef struct
BufferCacheOsPagesRec *record;
} BufferCacheOsPagesContext;
+static TupleDesc build_buffercache_pages_tupledesc(int natts);
+
/*
* Function returning data from the shared buffer cache - buffer number,
@@ -86,6 +88,8 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc expected_tupledesc;
+ TupleDesc actual_tupledesc;
+ MemoryContext oldcontext;
int i;
/*
@@ -105,6 +109,21 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
InitMaterializedSRF(fcinfo, 0);
+ oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
+ actual_tupledesc = build_buffercache_pages_tupledesc(expected_tupledesc->natts);
+ MemoryContextSwitchTo(oldcontext);
+
+ /*
+ * Override the caller-supplied descriptor with the tuple descriptor that
+ * matches the values we actually return, so executor-side
+ * tupledesc_match() can verify the caller's row definition.
+ *
+ * Do not free the previous rsinfo->setDesc here: for RECORD results it
+ * can alias rsinfo->expectedDesc, which the executor still needs to
+ * reference.
+ */
+ rsinfo->setDesc = actual_tupledesc;
+
/*
* Scan through all the buffers, adding one row for each of the buffers to
* the tuplestore.
@@ -205,6 +224,38 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
return (Datum) 0;
}
+static TupleDesc
+build_buffercache_pages_tupledesc(int natts)
+{
+ TupleDesc tupledesc;
+
+ tupledesc = CreateTemplateTupleDesc(natts);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relforknumber",
+ INT2OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 6, "relblocknumber",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 7, "isdirty",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usagecount",
+ INT2OID, -1, 0);
+
+ if (natts == NUM_BUFFERCACHE_PAGES_ELEM)
+ TupleDescInitEntry(tupledesc, (AttrNumber) 9, "pinning_backends",
+ INT4OID, -1, 0);
+
+ TupleDescFinalize(tupledesc);
+
+ return BlessTupleDesc(tupledesc);
+}
+
/*
* Inquire about OS pages mappings for shared buffers, with NUMA information,
* optionally.
diff --git a/contrib/pg_buffercache/sql/pg_buffercache.sql b/contrib/pg_buffercache/sql/pg_buffercache.sql
index 127d604905c..be89b5f5a3a 100644
--- a/contrib/pg_buffercache/sql/pg_buffercache.sql
+++ b/contrib/pg_buffercache/sql/pg_buffercache.sql
@@ -34,6 +34,12 @@ SELECT count(*) > 0 FROM pg_buffercache;
SELECT count(*) > 0 FROM pg_buffercache_os_pages;
SELECT buffers_used + buffers_unused > 0 FROM pg_buffercache_summary();
SELECT count(*) > 0 FROM pg_buffercache_usage_counts();
+SELECT *
+FROM pg_buffercache_pages() AS p
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+ relforknumber smallint, relblocknumber bigint, isdirty text,
+ usagecount smallint)
+LIMIT 1;
RESET role;
--
2.53.0
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 03:42 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
2026-06-05 07:58 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
@ 2026-06-05 08:47 ` Ayush Tiwari <[email protected]>
2026-06-08 23:44 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Ayush Tiwari @ 2026-06-05 08:47 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Калинин Никита <[email protected]>; PostgreSQL mailing lists <[email protected]>
Hi,
On Fri, 5 Jun, 2026, 13:28 Fujii Masao, <[email protected]> wrote:
> On Fri, Jun 5, 2026 at 12:42 PM Ayush Tiwari
> <[email protected]> wrote:
> > One small nit: build_buffercache_pages_tupledesc() names attribute 8
> > "usage_count", while the existing pg_buffercache view and the test use
> > "usagecount". This probably does not affect the tupledesc_match() check,
> > but I think it would be better to keep the existing spelling for
> > consistency.
>
> Agreed. I've fixed that and attached an updated version of the patch.
>
LGTM.
Regards,
Ayush
>
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 03:42 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
2026-06-05 07:58 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 08:47 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
@ 2026-06-08 23:44 ` Fujii Masao <[email protected]>
2026-06-10 03:34 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Fujii Masao @ 2026-06-08 23:44 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; +Cc: Калинин Никита <[email protected]>; PostgreSQL mailing lists <[email protected]>
On Fri, Jun 5, 2026 at 5:48 PM Ayush Tiwari <[email protected]> wrote:
>> Agreed. I've fixed that and attached an updated version of the patch.
>
>
> LGTM.
Barring any objections, I will commit the patch.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 03:42 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
2026-06-05 07:58 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 08:47 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ayush Tiwari <[email protected]>
2026-06-08 23:44 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
@ 2026-06-10 03:34 ` Fujii Masao <[email protected]>
0 siblings, 0 replies; 10+ messages in thread
From: Fujii Masao @ 2026-06-10 03:34 UTC (permalink / raw)
To: Ayush Tiwari <[email protected]>; +Cc: Калинин Никита <[email protected]>; PostgreSQL mailing lists <[email protected]>
On Tue, Jun 9, 2026 at 8:44 AM Fujii Masao <[email protected]> wrote:
>
> On Fri, Jun 5, 2026 at 5:48 PM Ayush Tiwari <[email protected]> wrote:
> >> Agreed. I've fixed that and attached an updated version of the patch.
> >
> >
> > LGTM.
>
> Barring any objections, I will commit the patch.
I've pushed the patch. Thanks!
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
@ 2026-06-05 15:29 ` Ashutosh Sharma <[email protected]>
2026-06-05 15:38 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
1 sibling, 1 reply; 10+ messages in thread
From: Ashutosh Sharma @ 2026-06-05 15:29 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: [email protected]; [email protected]
Hi Fujii-san,
On Fri, Jun 5, 2026 at 8:49 AM Fujii Masao <[email protected]> wrote:
>
> On Fri, Jun 5, 2026 at 12:49 AM PG Bug reporting form
> <[email protected]> wrote:
> >
> > The following bug has been logged on the website:
> >
> > Bug reference: 19508
> > Logged by: Nikita Kalinin
> > Email address: [email protected]
> > PostgreSQL version: 19beta1
> > Operating system: Fedora 44
> > Description:
> >
> > Hello,
> >
> > It appears that pg_buffercache_pages() trusts a caller-supplied record
> > descriptor without verifying that the declared column types match the actual
> > values returned by the function.
> >
> > The crash is reproducible on the current master branch with a fresh cluster
> > after installing the extension:
>
> Thanks for the report! I could reproduce this as well.
>
>
> > git blame points to the following commit:
> >
> > commit 257c8231bf97a77378f6fedb826b1243f0a41612 (HEAD)
> > Author: Heikki Linnakangas <[email protected]>
> > Date: Tue Apr 7 16:04:48 2026 +0300
> >
> > Modernize and optimize pg_buffercache_pages()
>
> Commit 257c8231bf9 changed pg_buffercache_pages() to materialize rows directly
> into a tuplestore. As a result, the function started using the caller-supplied
> RECORD descriptor as rsinfo->setDesc, so a mismatched column definition list
> could cause tuplestore_putvalues() to interpret returned Datums with incorrect
> types.
>
> Before that change, pg_buffercache_pages() exposed its actual tuple descriptor
> to the executor, allowing the executor's existing rowtype checks to reject
> incompatible definitions with a normal error.
>
> The attached patch restores that behavior while keeping the materialized-SRF
> implementation. Thoughts?
>
pg_buffercache_pages uses RETURNS SETOF RECORD whereas other
extensions like pgstattuple define explicit IN/OUT parameters at the
SQL level. Is there a specific reason this pattern was kept, or is it
simply a legacy design that hasn't been modernized? Had we followed
the IN/OUT parameter style, this sort of issue could have been
avoided, no?
--
With Regards,
Ashutosh Sharma.
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 15:29 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ashutosh Sharma <[email protected]>
@ 2026-06-05 15:38 ` Fujii Masao <[email protected]>
2026-06-09 04:38 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ashutosh Sharma <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Fujii Masao @ 2026-06-05 15:38 UTC (permalink / raw)
To: Ashutosh Sharma <[email protected]>; +Cc: [email protected]; [email protected]
On Sat, Jun 6, 2026 at 12:29 AM Ashutosh Sharma <[email protected]> wrote:
> pg_buffercache_pages uses RETURNS SETOF RECORD whereas other
> extensions like pgstattuple define explicit IN/OUT parameters at the
> SQL level. Is there a specific reason this pattern was kept, or is it
> simply a legacy design that hasn't been modernized? Had we followed
> the IN/OUT parameter style, this sort of issue could have been
> avoided, no?
Probably yes. But if we do that, we would likely need to bump pg_buffercache
version. I'm not sure that's worthwhile just for this change.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
2026-06-05 15:29 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Ashutosh Sharma <[email protected]>
2026-06-05 15:38 ` Re: BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition Fujii Masao <[email protected]>
@ 2026-06-09 04:38 ` Ashutosh Sharma <[email protected]>
0 siblings, 0 replies; 10+ messages in thread
From: Ashutosh Sharma @ 2026-06-09 04:38 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: [email protected]; [email protected]
On Fri, Jun 5, 2026 at 9:08 PM Fujii Masao <[email protected]> wrote:
>
> On Sat, Jun 6, 2026 at 12:29 AM Ashutosh Sharma <[email protected]> wrote:
> > pg_buffercache_pages uses RETURNS SETOF RECORD whereas other
> > extensions like pgstattuple define explicit IN/OUT parameters at the
> > SQL level. Is there a specific reason this pattern was kept, or is it
> > simply a legacy design that hasn't been modernized? Had we followed
> > the IN/OUT parameter style, this sort of issue could have been
> > avoided, no?
>
> Probably yes. But if we do that, we would likely need to bump pg_buffercache
> version. I'm not sure that's worthwhile just for this change.
>
Okay, that makes perfect sense, thanks for the confirmation.
--
With Regards,
Ashutosh Sharma.
^ permalink raw reply [nested|flat] 10+ messages in thread
end of thread, other threads:[~2026-06-10 03:34 UTC | newest]
Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-04 14:35 BUG #19508: pg_buffercache_pages() crashes the backend with an incompatible caller-supplied record definition PG Bug reporting form <[email protected]>
2026-06-05 03:18 ` Fujii Masao <[email protected]>
2026-06-05 03:42 ` Ayush Tiwari <[email protected]>
2026-06-05 07:58 ` Fujii Masao <[email protected]>
2026-06-05 08:47 ` Ayush Tiwari <[email protected]>
2026-06-08 23:44 ` Fujii Masao <[email protected]>
2026-06-10 03:34 ` Fujii Masao <[email protected]>
2026-06-05 15:29 ` Ashutosh Sharma <[email protected]>
2026-06-05 15:38 ` Fujii Masao <[email protected]>
2026-06-09 04:38 ` Ashutosh Sharma <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox