]> git.ipfire.org Git - thirdparty/postgresql.git/log
thirdparty/postgresql.git
3 weeks agoRe-index ModifyTable FDW arrays when pruning result relations
Amit Langote [Mon, 22 Jun 2026 08:21:45 +0000 (17:21 +0900)] 
Re-index ModifyTable FDW arrays when pruning result relations

ExecInitModifyTable() rebuilds the per-result-relation lists after
dropping result relations removed by initial runtime pruning.  The
re-indexing was done for withCheckOptionLists, returningLists,
updateColnosLists, mergeActionLists and mergeJoinConditions, but
fdwPrivLists and fdwDirectModifyPlans were missed.  As a result, a
kept foreign result relation could be handed the wrong fdw_private,
or ri_usesFdwDirectModify could be set from the wrong plan index,
leading to wrong behavior or a crash in BeginForeignModify() and in
the direct-modify path.

show_modifytable_info() had the same problem: it indexed the
plan-ordered node->fdwPrivLists with the post-pruning executor
position, so once initial pruning removed a result relation it
could read a different relation's fdw_private (often a NIL entry),
producing wrong EXPLAIN output or a crash.

Fix by re-indexing fdwPrivLists and fdwDirectModifyPlans alongside
the other lists, saving the re-indexed private lists in
ModifyTableState.mt_fdwPrivLists and reading from there in both
nodeModifyTable.c and explain.c.

Reported-by: Chi Zhang <798604270@qq.com>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Author: Rafia Sabih <rafia.pghackers@gmail.com>
Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Etsuro Fujita <etsuro.fujita@gmail.com>
Discussion: https://postgr.es/m/19484-a3cb82c8cde3c8fa%40postgresql.org
Backpatch-through: 18

3 weeks agodoc: Describe better handling of indexes in ALTER TABLE ATTACH PARTITION
Michael Paquier [Tue, 23 Jun 2026 07:52:15 +0000 (16:52 +0900)] 
doc: Describe better handling of indexes in ALTER TABLE ATTACH PARTITION

When ALTER TABLE ... ATTACH PARTITION matches partition indexes to the
parent table's indexes, invalid indexes are skipped.  This commit
improves the documentation to describe what e90e9275f56 has changed:
invalid indexes are skipped, and only valid indexes are considered for a
match.

Author: Mohamed Ali <moali.pg@gmail.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/CAGnOmWpAMaE-BOkpwM6mJnHcpS2QZ8yLSSaqmz+vryEsbCWWWA@mail.gmail.com
Backpatch-through: 14

3 weeks agoRe-introduce pgstat_drop_entry(), keeping ABI compatibility
Michael Paquier [Mon, 22 Jun 2026 22:58:04 +0000 (07:58 +0900)] 
Re-introduce pgstat_drop_entry(), keeping ABI compatibility

This routine acts as a wrapper of a new pgstat_drop_entry_ext(), used in
the core code with a missing_ok argument.

This includes an update of .abi-compliance-history, removing the latest
entry that has documented the change of pgstat_drop_entry().  This
change is applied across v15~v18.  HEAD keeps pgstat_drop_entry() as
single entry point, with the new missing_ok.

Per discussion with Álvaro Herrera and Lukas Fittl.  This is a follow-up
of 850b9218c8e4.

Discussion: https://postgr.es/m/ajZz_sVJVX7pmPHo@alvherre.pgsql
Backpatch-through: 15-18

3 weeks agoFix unsafe order of operations in ResourceOwnerReleaseAll().
Tom Lane [Mon, 22 Jun 2026 22:03:23 +0000 (18:03 -0400)] 
Fix unsafe order of operations in ResourceOwnerReleaseAll().

This function called the resource-kind-specific ReleaseResource()
method for each item before deleting that item from the resowner.
That's backwards from the ordering in ResourceOwnerReleaseAllOfKind,
and it's not very safe.  If ReleaseResource throws an error then the
subsequent abort cleanup will come back here and try to release that
item again, possibly leading to a double-free or similar crash,
and in any case risking an infinite error cleanup loop.  This mistake
explains why the pgcrypto bug just fixed in 80bb0ebcc led to a crash
rather than something more benign.

Remove the item from the resowner, then call ReleaseResource,
matching the way things were done before b8bff07da.  If there
is a problem of this sort, we'd prefer to leak the item than
suffer the other likely consequences.

Per further analysis of bug #19527.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/646741.1782157515@sss.pgh.pa.us
Backpatch-through: 17

3 weeks agopgcrypto: avoid recursive ResourceOwnerForget().
Tom Lane [Mon, 22 Jun 2026 16:59:16 +0000 (12:59 -0400)] 
pgcrypto: avoid recursive ResourceOwnerForget().

Raising an error within a function using an OSSLCipher object led
to a complaint from ResourceOwnerForget and then a double-free crash,
because ResOwnerReleaseOSSLCipher forgot to unhook the OSSLCipher
object from its owner.  (The sibling logic for OSSLDigest objects got
this right, as did every other ReleaseResource function AFAICS.)

Oversight in cd694f60d.

Bug: #19527
Reported-by: Yuelin Wang <3020001251@tju.edu.cn>
Author: Yuelin Wang <3020001251@tju.edu.cn>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19527-6e7686960c6dce78@postgresql.org
Backpatch-through: 17

3 weeks agoStrip removed-relation references from PlaceHolderVars at join removal
Richard Guo [Mon, 22 Jun 2026 01:43:01 +0000 (10:43 +0900)] 
Strip removed-relation references from PlaceHolderVars at join removal

When left-join removal deletes a relation, remove_rel_from_query()
updates the relid sets attached to RestrictInfos and
EquivalenceMembers, and the canonical PlaceHolderVar held in each
PlaceHolderInfo, but it does not rewrite the PlaceHolderVars embedded
in clause and EquivalenceClass member expressions.  That has been
fine, because later processing consults those relid sets rather than
the embedded PlaceHolderVars.

However, such an expression may afterwards be translated for an
appendrel child and have its relids recomputed from scratch by
pull_varnos().  If the embedded PlaceHolderVar's phrels still mentions
the removed relation, pull_varnos() folds it back in, so the rebuilt
clause's relids reference a no-longer-existent relation.  That yields
a parameterized path keyed on the removed relation, tripping the
Assert on root->outer_join_rels in get_eclass_indexes_for_relids().

Fix by stripping the removed relids from the PlaceHolderVars in
surviving rels' baserestrictinfo and in EquivalenceClass member
expressions, keeping them consistent with the canonical
PlaceHolderVars.

This is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars; before that,
the wrapping PlaceHolderVar prevented the index match that exposes the
stale relids.

Reported-by: Alexander Kuzmenkov <akuzmenkov@tigerdata.com>
Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Discussion: https://postgr.es/m/CALzhyqwryL2QywgO03VQr_237Sq3MEVgTTT2_A9G3nGT5-SRZg@mail.gmail.com
Backpatch-through: 18

3 weeks agoMake pg_mkdir_p() tolerant of a concurrent directory creation.
Tom Lane [Fri, 19 Jun 2026 16:52:00 +0000 (12:52 -0400)] 
Make pg_mkdir_p() tolerant of a concurrent directory creation.

pg_mkdir_p creates each missing path component with a stat() followed
by mkdir().  If the stat() reports the component as absent but another
process creates it in the window before this process's mkdir(), mkdir()
fails with EEXIST and pg_mkdir_p treated that as a hard error -- unlike
"mkdir -p", which is meant to be idempotent and race-tolerant.

This shows up when several processes concurrently create paths that
share an ancestor directory: for example, parallel initdb runs whose
data directories live under a common temporary directory.  One process
wins the race to create the shared ancestor and the others fail with
    could not create directory "...": File exists

Fix this race condition by first trying mkdir() and only attempting
stat() if it fails with EEXIST.

On Windows, there's an additional problem: stat() opens a file handle
and participates in share-mode locking, which means it can transiently
fail on a directory another process is concurrently creating.  Use
GetFileAttributes() instead: it requests only FILE_READ_ATTRIBUTES
and is exempt from share-mode denial, so it reliably sees a
concurrently-created directory.

I (tgl) also chose to back-patch 039f7ee0f's effects on this function,
so that pgmkdirp.c remains identical in all live branches.

Author: Andrew Dunstan <andrew@dunslane.net>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/3ca004de-e49b-4471-b8aa-fd656e70f68c@dunslane.net
Backpatch-through: 14

3 weeks agoUpdate JIT tuple deforming code for virtual generated columns
David Rowley [Fri, 19 Jun 2026 03:26:51 +0000 (15:26 +1200)] 
Update JIT tuple deforming code for virtual generated columns

The JIT deforming code contains an optimization that determines which
columns are guaranteed to exist in the tuple.  That's used to allow
skipping of reading the tuple's natts when the code only needs to deform
attributes that are guaranteed to always exist in all tuples.  83ea6c540
missed updating this code to account for VIRTUAL generated columns.
These are stored as NULLs in the tuple, but may be defined as NOT NULL.
This could result in the code thinking more columns are guaranteed to
exist than actually do.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Backpatch-through: 18
Discussion: https://postgr.es/m/1151393.1781734980@sss.pgh.pa.us

3 weeks agoSilence "may be used uninitialized" compiler warning.
Nathan Bossart [Thu, 18 Jun 2026 16:29:49 +0000 (11:29 -0500)] 
Silence "may be used uninitialized" compiler warning.

Newer gcc warns that this "actual_arg_types" variable may be used
uninitialized, but visual inspection indicates there's no bug.  To
silence the warning, initialize the variable to zeros.

Bug: #19485
Reported-by: Hans Buschmann <buschmann@nidsa.net>
Tested-by: Erik Rijkers <er@xs4all.nl>
Tested-by: Hans Buschmann <buschmann@nidsa.net>
Reviewed-by: Tristan Partin <tristan@partin.io>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/19485-2b03231a775756f1%40postgresql.org
Discussion: https://postgr.es/m/6c52a1a6612948519468d46cb224a8c4%40nidsa.net

3 weeks agohstore_plperl: Add CHECK_FOR_INTERRUPTS() in reference-unwinding loop.
Tom Lane [Thu, 18 Jun 2026 16:22:55 +0000 (12:22 -0400)] 
hstore_plperl: Add CHECK_FOR_INTERRUPTS() in reference-unwinding loop.

Add CHECK_FOR_INTERRUPTS() to the while loop in plperl_to_hstore()
that dereferences chains of Perl references, so that a circular
reference (e.g. $x = \$x) can be cancelled by the user instead of
spinning indefinitely.  (We looked at detecting such circular
references, but it seems more trouble than it's worth.)

This is a follow-up to da82fbb8f, which fixed the same issue in
SV_to_JsonbValue() in jsonb_plperl.

Author: Aleksander Alekseev <aleksander@tigerdata.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAJ7c6TPbjkzUk4qJ5dHvDNEz0hBuFue3A-XWz_=897z+BC+z8A@mail.gmail.com
Backpatch-through: 14

3 weeks agodoc: Fix "Prev" link, take 2.
Nathan Bossart [Thu, 18 Jun 2026 14:31:27 +0000 (09:31 -0500)] 
doc: Fix "Prev" link, take 2.

Commit 6678b58d78 fixed a wrong "Prev" link by changing the link
generation code to use [position()=last()] instead of [last()] in
the predicate on the union of reverse axes.  Unfortunately, that
caused documentation builds to take much longer.  To fix, combine
the "preceding" and "ancestor" steps into one "preceding" step and
one "ancestor" step, and revert the predicate back to [last()].
The smaller union evades the libxml2 bug while avoiding the build
time regression.

Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Tested-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/1132496.1781718007%40sss.pgh.pa.us
Backpatch-through: 14

3 weeks agoUpdate .abi-compliance-history for pgstat_drop_entry()
Michael Paquier [Thu, 18 Jun 2026 05:48:37 +0000 (14:48 +0900)] 
Update .abi-compliance-history for pgstat_drop_entry()

As noted in the commit message of 850b9218c8e4, this function has gained
an extra called "missing_ok".  All the callers of this routine should be
in core in the v15-v17 range.  For v18, I have found one custom stats
kind that would be impacted by this change.

Discussion: https://postgr.es/m/ajOE3uRxVgSlPRcw@paquier.xyz
Backpatch-through: 15-18

3 weeks agoAvoid stale slot access after dropping obsolete synced slots.
Amit Kapila [Thu, 18 Jun 2026 04:12:56 +0000 (09:42 +0530)] 
Avoid stale slot access after dropping obsolete synced slots.

drop_local_obsolete_slots() continued to dereference local_slot after
calling ReplicationSlotDropAcquired().  Once the slot is dropped, its
entry in the slot array can be reused by another backend, so later reads
of local_slot->data could observe a different slot's name or database
OID, leading to an incorrect unlock and log message.

Save the slot name and database OID before performing the drop, and use
the saved values for the subsequent UnlockSharedObject() call and the log
message.  While at it, emit the "dropped replication slot" message only
when a slot was actually dropped, rather than unconditionally.

Author: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Backpatch-through: 17, where it was introduced
Discussion: https://postgr.es/m/TY4PR01MB177184FF9EE916F577E1F554194082@TY4PR01MB17718.jpnprd01.prod.outlook.com

3 weeks agoFix PANIC with track_functions due to concurrent drop of pgstats entries
Michael Paquier [Thu, 18 Jun 2026 02:49:34 +0000 (11:49 +0900)] 
Fix PANIC with track_functions due to concurrent drop of pgstats entries

pgstat_drop_entry_internal() generates an ERROR if facing a pgstats
entry already marked as dropped.  With a workload doing a lot of
concurrent CALL and DROP/CREATE PROCEDURE, it could be possible for
AtEOXact_PgStat_DroppedStats(), that wants to do transactional drops, to
find entries that are already dropped, after a commit record has been
written.  In this case, ERRORs are upgraded to PANIC, taking down the
server.

This issue is fixed by making pgstat_drop_entry() optionally more
tolerant to concurrent drops, adding to the routine a missing_ok option
to make some of its callers more tolerant (spoiler: some of the callers
want a strict behavior, like replication slots and backend stats).
pgstat_drop_entry_internal() cannot be called anymore for an entry
marked as dropped, hence its error is replaced by an assertion.
Functions are handled as a special case in core; this problem could also
apply to custom stats kinds depending on what an extension does.
track_functions is costly when enabled (disabled by default), which is
perhaps the main reason why this has not be found yet.

A similar version of this patch has been proposed by Sami Imseih on a
different thread for a feature in development.  This version has tweaked
here by me for the sake of fixing this issue.

Reported-by: zhanglihui <zlh21343@163.com>
Author: Sami Imseih <samimseih@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/19520-73873648d44793cf@postgresql.org
Backpatch-through: 15

4 weeks agooauth: Skip call-count test for libcurl 8.20.0
Jacob Champion [Wed, 17 Jun 2026 16:57:59 +0000 (09:57 -0700)] 
oauth: Skip call-count test for libcurl 8.20.0

The call-count test in 001_server.pl runs into a recent upstream
regression in Curl:

    https://github.com/curl/curl/issues/21547

The symptom is high CPU usage on some platforms during OAuth HTTP
requests. But it looks like the fix is on track for a June 2026 release,
as part of Curl 8.21.0, so just skip the test if we happen to be using
the broken version.

Reported-by: Andrew Dunstan <andrew@dunslane.net>
Reported-by: Tom Lane <tgl@sss.pgh.pa.us>
Tested-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAOYmi%2B%3DyrwMSsHuNJ1V14isA4iSix5Xb3P3VEp1X0BS61MdV4A%40mail.gmail.com
Backpatch-through: 18

4 weeks agolibpq-oauth: Print libcurl version with OAUTHDEBUG_UNSAFE_TRACE
Jacob Champion [Wed, 17 Jun 2026 16:57:20 +0000 (09:57 -0700)] 
libpq-oauth: Print libcurl version with OAUTHDEBUG_UNSAFE_TRACE

When debugging an OAuth trace, it's helpful to know what version of Curl
is in use. The SSL library that Curl is using (which may not be the one
in use by libpq) is also relevant, and it's just as easy to get, so
print that too.

This is being added post-feature-freeze, with RMT approval, in order to
fix some tests in the face of an upstream Curl regression. A subsequent
commit will make use of it in oauth_validator. Backpatch to 18 as well.

Tested-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAOYmi%2B%3DkP86t%2BZFFXNQ9G6K4ht7utdmB%3DCzhP%3DZ2wvuBymOTtQ%40mail.gmail.com
Backpatch-through: 18

4 weeks agooauth_validator: Print captured stderr after call-count failure
Jacob Champion [Wed, 17 Jun 2026 16:57:15 +0000 (09:57 -0700)] 
oauth_validator: Print captured stderr after call-count failure

If the call count test fails, you'll reasonably want to know what the
network trace looked like, but that information is currently swallowed.
Print it out instead.

Backpatch-through: 18

4 weeks agojsonb_plperl, jsonb_plpython: Fix unguarded recursion and loops.
Tom Lane [Wed, 17 Jun 2026 15:04:41 +0000 (11:04 -0400)] 
jsonb_plperl, jsonb_plpython: Fix unguarded recursion and loops.

Add check_stack_depth() to Jsonb_to_SV, SV_to_JsonbValue,
PLyObject_FromJsonbContainer, and PLyObject_ToJsonbValue.  Without
this, deeply nested JSONB values can crash the backend with SIGSEGV
instead of raising a proper error.

Also add CHECK_FOR_INTERRUPTS() to the while loop in SV_to_JsonbValue
that dereferences chains of Perl references, so that a circular
reference (e.g. $x = \$x) can be cancelled by the user instead of
spinning indefinitely.  (We looked at detecting such circular
references, but it seems more trouble than it's worth.)

Author: Aleksander Alekseev <aleksander@tigerdata.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAJ7c6TPbjkzUk4qJ5dHvDNEz0hBuFue3A-XWz_=897z+BC+z8A@mail.gmail.com
Backpatch-through: 14

4 weeks agovacuumdb: Fix --missing-stats-only for partitioned indexes.
Nathan Bossart [Wed, 17 Jun 2026 14:18:39 +0000 (09:18 -0500)] 
vacuumdb: Fix --missing-stats-only for partitioned indexes.

The current form of the catalog query picks up partitioned tables
with expression indexes that lack statistics.  However, since such
indexes never have statistics, there's no point in analyzing them.
To fix, adjust the relevant part of the query to skip partitioned
tables with expression indexes.  While at it, remove the nearby
stainherit check; entries for index expressions always have
stainherit = false.

Author: Baji Shaik <baji.pgdev@gmail.com>
Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
Discussion: https://postgr.es/m/CA%2Bfm-RPE1tEc6CUUPDyRbYTz9tF5Kw47nnk-Zq%3DyYvanbsxyCQ%40mail.gmail.com
Backpatch-through: 18

4 weeks agoFix pgstat_count_io_op_time() calls passing incorrect information
Michael Paquier [Wed, 17 Jun 2026 07:05:37 +0000 (16:05 +0900)] 
Fix pgstat_count_io_op_time() calls passing incorrect information

Several calls of pgstat_count_io_op_time() have been used as data to
count negative values returned by pg_pread() or pg_pwrite(), leading to
an incorrect count reported, casting them back to uint64.

Most of the problematic calls updated here are adjusted so as we do not
report buggy negative numbers anymore.  In xlogrecovery.c, the spot
updated still counts short reads.  In xlog.c, after a WAL segment
initialization, I/O numbers are aggregated only after checking that the
operation has succeeded.

issues introduced by a051e71e28a1.

Reported-by: Peter Eisentraut <peter@eisentraut.org>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/0db864e6-4477-4eba-b2be-d3523cc86564@eisentraut.org
Backpatch-through: 18

4 weeks agoFix another instability in recovery TAP test 004_timeline_switch
Michael Paquier [Tue, 16 Jun 2026 23:42:08 +0000 (08:42 +0900)] 
Fix another instability in recovery TAP test 004_timeline_switch

The test did not wait for the standby to be connected to the primary.
This breaks one assumption at the beginning of the test, where the
primary is stopped to ensure that all its records are flushed to both
standbys before moving on with its next steps.

If standby_1 finishes ahead of standby_2, the test would be able work
fine as the former waits for the latter.  The opposite is not true,
standby_2 getting ahead of standby_1 would cause the test to fail on
timeout when standby_1 attempts to connect to standby_2.

This commit adds an additional polling query after the two standbys are
started, checking that both standbys are connected to the primary before
processing with the initial steps of the test.

Like 7185eddf0522, backpatch down to v14.

Author: Sergey Tatarintsev <s.tatarintsev@postgrespro.ru>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Discussion: https://postgr.es/m/fea4190e-f8b5-4432-a52d-bcbee5f34366@postgrespro.ru
Backpatch-through: 14

4 weeks agological decoding: Correctly free speculative insertion
Álvaro Herrera [Tue, 16 Jun 2026 16:13:15 +0000 (18:13 +0200)] 
logical decoding: Correctly free speculative insertion

The error path in ReorderBufferProcessTXN was not freeing
(reorderbuffer.c's representation of) a speculative insertion record
correctly.  In assert-enabled builds, this leads to an assertion
failure.  In production builds, I see no effect; there may be a small
transient leak, but in an improbable code path such as this, such a leak
is not of any significance.  For users running with assertions enabled,
the crash is annoying.

Fix by having ReorderBufferProcessTXN() free the speculative insert
ahead of freeing the rest of the transaction, and no longer try to
handle that insert as a separate argument to ReorderBufferResetTXN().

This code came in with commit 7259736a6e5b (14-era).  Backpatch all the
way back.

In branches 14-16, also backpatch the assertion that originally fails in
the problem scenario, which was added by dbed2e36625d (originally
backpatched to 17), that at the end of ReorderBufferReturnTXN() the
in-memory size of the transaction is zero.

Author: Vishal Prasanna <vishal.g@zohocorp.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Backpatch-through: 14
Discussion: https://postgr.es/m/19c7623e882.4080fd5426212.311756747309556767@zohocorp.com

4 weeks agopg_restore: Use dependency-based matching for STATISTICS DATA
Michael Paquier [Tue, 16 Jun 2026 06:58:17 +0000 (15:58 +0900)] 
pg_restore: Use dependency-based matching for STATISTICS DATA

The previous approach introduced by 0dd93de69e80 was weak in terms of
name matching, as an --index=foo could match with a table with the same
name but from a different schema, pulling in more data than necessary.

For example, imagine the following case:
CREATE SCHEMA s1;
CREATE SCHEMA s2;
CREATE TABLE s1.foo (id int);
INSERT INTO s1.foo SELECT generate_series(1,100);
ANALYZE s1.foo;
CREATE TABLE s2.bar (id int);
CREATE INDEX foo ON s2.bar(id);
INSERT INTO s2.bar SELECT generate_series(1,100);
ANALYZE s2.bar;

A targetted pg_restore --index=foo would grab the relation and attribute
stats of s1.foo on top of the index s2.foo, which is incorrect.  This
commit fixes this scenario by relying on a lookup of the dependencies of
a STATISTICS DATA TOC entry, checking if a TOC entry depends on an index
or another relkind before matching with the names of the objects wanted
for the restore.

Discussion: https://postgr.es/m/ajDBwpxs-otl585H@paquier.xyz
Backpatch-through: 18

4 weeks agoFix int32 overflow in ltree_compare()
Heikki Linnakangas [Tue, 16 Jun 2026 06:27:00 +0000 (09:27 +0300)] 
Fix int32 overflow in ltree_compare()

The expression (len_diff * 10 * (an + 1)) used as the return value of
ltree_compare() is computed at int32 width.  With LTREE_MAX_LEVELS =
65535, the product can exceed INT32_MAX once an ltree has more than
~14,653 levels, which causes the result to wrap and invert its sign.
That corrupts btree ordering as well as the "magnitude" consumed by
ltree_penalty() for GiST page splits.

To fix, split ltree_compare() into two functions.  The new
ltree_compare_distance() function returns a float, which won't
overflow.  It's used by the ltree_penalty() caller.  All the other
callers only care about the sign of the return value, i.e. which of
the arguments is greater, so change ltree_compare() to not multiply
the result with (10 * (an + 1)), which avoids the overflow for those
callers.

Existing btree or GiST indexes on ltree columns containing values with
more than ~14,653 levels may be corrupt and should be REINDEXed.

Add a regression test based on the reporter's PoC.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reported-by: 王跃林 <violin0613@tju.edu.cn>
Discussion: https://www.postgresql.org/message-id/AI6AnABgKW93Qbx1jVzi84r9.8.1781322625756.Hmail.3020001251%40tju.edu.cn
Backpatch-through: 14

4 weeks agopg_dump: Remove dead code in TAP tests
Michael Paquier [Mon, 15 Jun 2026 23:31:43 +0000 (08:31 +0900)] 
pg_dump: Remove dead code in TAP tests

The schema_only_with_statistics test scenario was referenced in
002_pg_dump.pl, but was associated to no command sequence since
0ed92cf50cc4.

Issue discovered while investigating a different bug.  Perhaps this
cleanup is not worth backpatching, but there is also an argument in
favor of reducing noise when touching this area of the code in stable
branches.

Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/ai-y0S7Z25NlrG_n@paquier.xyz
Backpatch-through: 18

4 weeks agoFix inconsistencies with pg_restore --statistics[-only]
Michael Paquier [Mon, 15 Jun 2026 23:22:41 +0000 (08:22 +0900)] 
Fix inconsistencies with pg_restore --statistics[-only]

Attempting to restore a schema, a table or an index with
--only-statistics skipped all the statistics of the objects wanted.
Like for pg_dump, statistics should be included, so this created an
assymetry between dump and restore.

A second set of problems existed for --table and --index, where the
presence of --statistics skipped the restore of the stats of the
object(s) targetted.

This issue has been reported originally as related to an inconsistency
with the way extended stats restore is handled in Postgres v19, but the
issue is related to the restore of relation and attribute statistics in
v18.  Some TAP tests are added to cover all these cases.

Reported-by: Chao Li <li.evan.chao@gmail.com>
Author: Chao Li <li.evan.chao@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
Discussion: https://postgr.es/m/66E80CAB-527C-42B1-BB65-3F82CF4AD998@gmail.com
Backpatch-through: 18

4 weeks agoClean up quoting of variable strings within replication commands.
Tom Lane [Mon, 15 Jun 2026 19:35:37 +0000 (15:35 -0400)] 
Clean up quoting of variable strings within replication commands.

Our handling of quoting within replication commands was pretty
sloppy, typically looking like
        appendStringInfo(&cmd, " SLOT \"%s\"", options->slotname);
This is fine as long as options->slotname doesn't contain a double
quote mark, but what if it does?  In principle this'd allow injection
of harmful options into replication commands, in the probably-unlikely
case that a slot name comes from untrustworthy input.  We ought to
clean that up.

Moreover, even the places that were trying to be more careful
generally got it wrong, because they used quoting subroutines
intended for SQL commands rather than something that will work
with the replication-command scanner repl_scanner.l.  For example,
several places naively use PQescapeLiteral() to quote option values
for replication commands.  If the string contains a backslash,
PQescapeLiteral() will produce E'...' literal syntax, which
repl_scanner.l doesn't recognize.  Another near miss was to use
quote_identifier() to quote identifiers.  That function won't quote
valid lowercase identifiers unless they match SQL keywords ... but in
this context, replication keywords are what matter.  Neither of these
errors seem to risk string injection, but they definitely can cause
syntax errors in replication commands that ought to be valid.

We can clean all this up by using simple quoting logic that just
doubles single or double quotes respectively.

Or at least, we could if repl_scanner.l handled doubled double quotes
in identifiers, but for some reason it doesn't!  So the first step in
this fix has to be to fix that.  (The fact that we'll later reject
slot names containing double quotes is very far short of justifying
this omission.)

Having done that, this patch runs around and applies correct
quoting in all places that generate replication commands containing
strings coming from outside the immediate context.  Probably some
of these places are safe because of restrictions elsewhere, but it
seems best to just quote all the time.

This was originally reported as a security bug, which it could be
if replication slot names or parameters were to originate from
untrustworthy sources.  But the security team concluded that that
was a very improbable situation, so we're just going to fix this
as a regular bug.

Reported-by: Team Dhiutsa
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/1648659.1781287310@sss.pgh.pa.us
Backpatch-through: 14

4 weeks agodoc: Fix "Prev" link.
Nathan Bossart [Mon, 15 Jun 2026 17:16:38 +0000 (12:16 -0500)] 
doc: Fix "Prev" link.

Presently, the "Prev" link on the page for background workers sends
you to the middle of the previous chapter instead of the actual
previous page.  This appears to be caused by a libxml2 bug, but
regardless, a minimal fix is to change the link generation code to
use [position()=last()] instead of [last()] in the predicate on the
union of reverse axes.

Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/aim4AZorFKaC7Wrf%40nathan
Backpatch-through: 14

4 weeks agoModernize pg_bsd_indent's error/warning reporting code.
Tom Lane [Mon, 15 Jun 2026 16:22:55 +0000 (12:22 -0400)] 
Modernize pg_bsd_indent's error/warning reporting code.

Late-model clang complains that these functions should be labeled
with "format(printf, 2, 3)", and it's right.  But let's go a bit
further and also make use of varargs, to remove duplication and
allow these functions to be used with non-integer input values.

Since no good deed goes unpunished, I had to also adjust a couple
of call sites.  They weren't wrong as-is, since the size_t-sized
arguments were coerced to int on the way into diag3().  But
without that, we have to adjust the format strings.

The point of this is to suppress compiler warnings, so back-patch
into branches containing pg_bsd_indent, even though there's no
functional change.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/1645041.1781283554@sss.pgh.pa.us
Backpatch-through: 16

4 weeks agoFix PQdescribePrepared with more than 7498 params
Heikki Linnakangas [Mon, 15 Jun 2026 08:28:45 +0000 (11:28 +0300)] 
Fix PQdescribePrepared with more than 7498 params

If a query has more than 7498 params, the ParameterDescription message
exceeds the 30000 byte limit on messages that are not specifically
marked as possibly being longer than that (VALID_LONG_MESSAGE_TYPE).
To fix, add ParameterDescription to the list.

Author: Ning Sun <classicning@gmail.com>
Discussion: https://www.postgresql.org/message-id/dbfb4b65-0aa8-470a-8b87-b6496160b28a@gmail.com
Backpatch-through: 14

4 weeks agoTrim regression test expected output for xml
Michael Paquier [Mon, 15 Jun 2026 02:37:55 +0000 (11:37 +0900)] 
Trim regression test expected output for xml

This commit reduces the number of expected output files for the "xml"
test from three to two (well, mostly one, see below for details).

xml_2.out existed to handle some differences in output due to libxml2
2.9.3, due to some error context missing (085423e3e326).  This file is
removed, by tweaking the XML inputs to trigger the same error patterns
for the problematic 2.9.3 and other libxml2 versions.  This part is
authored by Tom Lane.

xml_1.out (no libxml2 support) is reduced in size by adding an \if query
that exits the test early.  This still checks NO_XML_SUPPORT() through
xmlin().  The rest of the test is skipped if XML input cannot be
handled by the backend.  This part has been written by me.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/aiu6CXO67q-s70n5@paquier.xyz
Backpatch-through: 14

4 weeks agoDoc: remove stale entry for removed aclitem[] ~ aclitem operator.
Tom Lane [Sun, 14 Jun 2026 15:01:48 +0000 (11:01 -0400)] 
Doc: remove stale entry for removed aclitem[] ~ aclitem operator.

Commit 2f70fdb06 removed the deprecated containment operator
~(aclitem[],aclitem) from the catalogs, but missed removing its entry
from the documentation.  (Arguably the blame should fall on c62dd80cd,
which added this entry in contravention of the longstanding policy
that we don't document deprecated aliases in the first place.)

Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAOzEurQSyR5psWukyhUz1LtxyO55C2Vfp0Fmt8w2jGKxhszQmQ@mail.gmail.com
Backpatch-through: 14

4 weeks agoamcheck: Use correct varlena size accessor in bt_normalize_tuple()
Alexander Korotkov [Sat, 13 Jun 2026 23:49:05 +0000 (02:49 +0300)] 
amcheck: Use correct varlena size accessor in bt_normalize_tuple()

bt_normalize_tuple() uses VARSIZE() to get the size of varlena, even though
it's not yet known, that it has a 4-byte header.  Fix this by replacing a
accessor with a universal VARSIZE_ANY().

Backpatch to all supported versions.

Reported-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/7ckc7oka4bvafkf5bwlqs6ygrhlsbhz25ppozfch7zbuxcx3rf%40e4pr4oqenalc
Author: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
Backpatch-through: 14

4 weeks agoAdjust cross-version upgrade tests for seg_out() fix
Andrew Dunstan [Fri, 12 Jun 2026 22:05:25 +0000 (18:05 -0400)] 
Adjust cross-version upgrade tests for seg_out() fix

Commit 0e1f1ed157e taught seg_out() to print the certainty indicator
on an interval's upper boundary, but it was back-patched only as far
as v14.  When upgrading from an older release, the old server prints
the one test_seg row exercising that case ('4.6 .. ~7.0') without the
indicator, so the pre- and post-upgrade dumps do not match.  Make
AdjustUpgrade.pm delete just that row; seg's comparison function does
distinguish the certainty indicators, so the otherwise identical row
'4.6 .. 7.0' is unaffected.

Back-patch to all supported branches.

Per buildfarm members crake and fairywren.

Discussion: https://postgr.es/m/5ccbdbde-6467-4a10-bf4d-0be73a05ce8d@dunslane.net

4 weeks agoFix compilation with OpenSSL 4
Daniel Gustafsson [Fri, 12 Jun 2026 11:57:22 +0000 (13:57 +0200)] 
Fix compilation with OpenSSL 4

OpenSSL 4.0.0 changed some parameters and returnvalues to const, so
we need to update our declarations and subsequently cast away const-
ness from a few callsites to make libpq build without warnings. This
is tested with OpenSSL 1.1.1 through 4.0.0 as well as with LibreSSL.
No functional change is introduced, this commit only allows postgres
to be compiled against OpenSSL 4.0.0 without warnings.

There is also an errormessage change in OpenSSL 4.0.0 which needed
to be covered by our testharness.

This will be backpatched to all supported branches since they are
all equally likely to be built against OpenSSL 4.0.0 as it becomes
available in distributions.  Backpatching will be done once it has
been in master for a few days without issues.

Author: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/066B07BB-85FA-487C-BE8C-40F791CFC3C4@yesql.se
Backpatch-through: 14

4 weeks agoUpdate expected regression test output for xml_2.out
Michael Paquier [Fri, 12 Jun 2026 03:37:21 +0000 (12:37 +0900)] 
Update expected regression test output for xml_2.out

This one has been forgotten in 8bf257aebac1.  Per report from buildfarm
member massasauga.

Backpatch-through: 14

4 weeks agoFix second race with timeline selection during promotion
Michael Paquier [Fri, 12 Jun 2026 02:44:14 +0000 (11:44 +0900)] 
Fix second race with timeline selection during promotion

read_local_xlog_page_guts has the same race as logical_read_xlog_page:
RecoveryInProgress() can return true during promotion, impacting the
availability of the operations doing WAL page reads with this callback.

This problem is similar to eb4e7224a1c6 that has addressed the issue for
logical replication, impacting more areas of the code where this WAL
page callback can be used (same narrow window during promotion, same
availability issue):
- pg_walinspect.
- Slot advance (SQL function).
- Slot creation.

Repack workers (v19~) and 2PC files (since forever) can also use this
callback, but they are irrelevant as far as I know.  A test is added
with the SQL lookup functions.  This part relies on injection points,
and is backpatched down to v18, like the test added for eb4e7224a1c6.

This issue could probably be fixed as well in v14 and v15 for
pg_walinspect.  However, I also feel that there is a conservative
argument about consistency here due to the support of logical decoding
on standbys, so let's limit ourselves to v16 for now.  pg_walinspect is
used less in the field compared to the two other operations, making
addressing this problem less attractive in these two older branches.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
Backpatch-through: 16

4 weeks agodoc: fix reference for finding replication slots to drop
Fujii Masao [Fri, 12 Jun 2026 02:08:33 +0000 (11:08 +0900)] 
doc: fix reference for finding replication slots to drop

Commit a70bce43fb added instructions on how to recover if PostgreSQL
refuses to issue new transaction IDs because of imminent wraparound,
but when describing how to find replication slots that should be dropped,
it referred to pg_stat_replication where it should have referenced
pg_replication_slots.

In passing, decorate references to views with <structname> tags.

Backpatch to all supported versions.

Reported-By: Sanjaya Waruna <sanjaya.waruna@gmail.com>
Author: Laurenz Albe <laurenz.albe@cybertec.at>
Reviewed-by: Robert Treat <rob@xzilla.net>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/176767268098.1084085.10345048667224193115@wrigleys.postgresql.org
Backpatch-through: 14

4 weeks agoFix handling of namespace nodes in xpath() (xml)
Michael Paquier [Fri, 12 Jun 2026 01:25:49 +0000 (10:25 +0900)] 
Fix handling of namespace nodes in xpath() (xml)

xpath() attempted to call xmlCopyNode() and xmlNodeDump() on a
XML_NAMESPACE_DECL, finishing with a confusing error:
=# SELECT xpath('//namespace::foo', '<root xmlns:foo="http://127.0.0.1"/>');
ERROR:  53200: could not copy node
CONTEXT:  SQL function "xpath" statement 1

xpath() is changed so as it goes through xmlXPathCastNodeToString()
instead, that is able to handle namespace nodes.  xml2 uses the same
solution.  This issue has been discovered while digging into
9d33a5a804db.

Author: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/aioT7ui_ZJ9RMlfM@paquier.xyz
Backpatch-through: 14

4 weeks agoamcheck: Fix missing allequalimage corruption report
Fujii Masao [Fri, 12 Jun 2026 00:35:27 +0000 (09:35 +0900)] 
amcheck: Fix missing allequalimage corruption report

When amcheck validates that a B-Tree metapage's allequalimage flag
matches _bt_allequalimage(), it could fail to report corruption
unless one of the index key columns used interval_ops. As a result,
pg_amcheck could silently miss this corruption on other opclasses,
incorrectly reporting the index as valid.

The mistake was that bt_index_check_callback() kept ereport(ERROR)
inside the loop that scans key attributes for INTERVAL_BTREE_FAM_OID,
even though that loop is only needed to decide whether to add
the interval-specific hint. This commit moves ereport() out of the loop
so allequalimage mismatches are always reported, while still emitting
the hint for affected interval indexes.

Back-patch to v18, where d70b17636dd introduced this regression
while moving the check into bt_index_check_callback().

Author: Chao Li <lic@highgo.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/011ACC9C-CB87-4160-ACE7-4ED57AB86E15@gmail.com
Backpatch-through: 18

4 weeks agoIS JSON/JSON(): Protect against expressions uncoercible to text
Álvaro Herrera [Thu, 11 Jun 2026 14:17:58 +0000 (16:17 +0200)] 
IS JSON/JSON(): Protect against expressions uncoercible to text

transformJsonParseArg() was not careful enough on generation of
transformed expressions when starting from expressions that are not
coercible to text but are in the string type category: it failed to
verify that coerce_to_target_type() succeeds, and returned a NULL
pointer.  This leads to a later NULL dereference and crash at executor
time.

This escaped noticed because it cannot happen for built-in types, all of
which have casts to text.  Only user-created types are potentially
problematic.

Fix by raising an error when a cast to text doesn't exist.

This mistake came in with commit 6ee30209a6f1.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reported-by: Chi Zhang <798604270@qq.com>
Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Backpatch-through: 16
Discussion: https://postgr.es/m/19491-7aafc221ec63f288@postgresql.org

4 weeks agoFix parsing of parenthesised OLD/NEW in RETURNING list.
Dean Rasheed [Thu, 11 Jun 2026 11:08:48 +0000 (12:08 +0100)] 
Fix parsing of parenthesised OLD/NEW in RETURNING list.

When parsing expressions like (old).colname and (old).* in a RETURNING
list, the parser would lose track of the intended varreturningtype,
and therefore return incorrect results.

The root cause was code using GetNSItemByRangeTablePosn() to find a
namespace item from its rtindex and levelsup, without taking into
account returningtype, which would return the wrong namespace item.
Fix by adding a new function GetNSItemByVar() that does take
returningtype into account.

Backpatch to v18, where support for RETURNING OLD/NEW was added.

Bug: #19516
Reported-by: Marko Grujic <markoog@gmail.com>
Author: Marko Grujic <markoog@gmail.com>
Suggested-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Discussion: https://postgr.es/m/CAOvwyF2cO_5mAt=w=y-dFnaG5UkZ+3H8nSDoKF_iuWZHsU2ARg@mail.gmail.com
Backpatch-through: 18

4 weeks agoseg: Fix seg_out() to preserve the upper boundary's certainty indicator
Heikki Linnakangas [Thu, 11 Jun 2026 09:33:48 +0000 (12:33 +0300)] 
seg: Fix seg_out() to preserve the upper boundary's certainty indicator

When printing the upper boundary of a seg interval, seg_out() decided
whether to emit the certainty indicator ('<', '>' or '~') by testing the
upper indicator (u_ext) for '<' and '>', but mistakenly tested the lower
indicator (l_ext) for '~'.  This is a copy-and-paste slip from the
symmetric code that prints the lower boundary a few lines above.

The consequences for valid input were:

  * A '~' on the upper boundary was dropped on output, e.g.
    '1.5 .. ~2.5'::seg printed as '1.5 .. 2.5'.

  * When the lower boundary carried '~' but the upper boundary had no
    indicator, the wrong test matched and sprintf(p, "%c", seg->u_ext)
    wrote a NUL byte (u_ext == '\0'), which truncated the result string
    and silently lost the entire upper boundary, e.g.
    '~6.5 .. 8.5'::seg printed as '~6.5 .. '.

Certainty indicators are documented to be preserved on output (they are
ignored by the operators, but kept as comments), so this broke the
input/output round-trip for the affected values.

The bug has existed since seg was added.  It went unnoticed because the
existing regression tests only exercised certainty indicators on
single-point segs, which are printed by a different branch of seg_out().
Add tests that place indicators on both boundaries of an interval.

Author: Ewan Young <kdbase.hack@gmail.com>
Discussion: https://www.postgresql.org/message-id/CAON2xHPYeRRCEVAv8XfE18KsEsEHCiYcJ5fOsoxFuMEfpxF1=g@mail.gmail.com
Backpatch-through: 14

4 weeks agoFix race with timeline selection in logical decoding during promotion
Michael Paquier [Thu, 11 Jun 2026 08:29:38 +0000 (17:29 +0900)] 
Fix race with timeline selection in logical decoding during promotion

During promotion, there is a window where RecoveryInProgress() returns
true but the WAL segments of the old timeline have already been removed.
A logical decoding could pick up the old timeline in this window when
reading a page, failing with the following error:
ERROR: requested WAL segment ... has already been removed

This issue does not lead to any data correctness issue, as retrying to
decode the data works in follow-up decoding attempts.  It impacts
availability, though.  Other WAL page read callbacks have a similar
issue, this commit takes care of what should be the noisiest code path:
logical decoding with START_REPLICATION in a WAL sender.

A TAP test, based on an injection point waiting in the startup process
after the segments have been removed/recycled, is added.  This part is
backpatched down to v17.

This issue has been causing sporadic failures in the buildfarm, and
was reproducible manually.  This issue happens since logical decoding on
standbys exists, down to v16.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3@gmail.com
Backpatch-through: 16

4 weeks agoxml2: Fix crash with namespace nodes in xpath_nodeset()
Michael Paquier [Thu, 11 Jun 2026 05:29:22 +0000 (14:29 +0900)] 
xml2: Fix crash with namespace nodes in xpath_nodeset()

pgxmlNodeSetToText() passed nodeTab[i]->doc to xmlNodeDump() without
checking the node type, which could cause a crash as a
XML_NAMESPACE_DECL maps to a xmlNs struct.  The passed-in code would
then be dereferenced in xmlNodeDump().

This commit switches the code to render XML_NAMESPACE_DECL nodes with
xmlXPathCastNodeToString(), like xpath_table().  Some tests are added,
written by me.

Author: Andrey Chernyy <andrey.cherny@tantorlabs.com>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/20260611031436.5afde3cb@andrnote
Backpatch-through: 14

5 weeks agoUse correct type for catalog_xmin
Fujii Masao [Mon, 8 Jun 2026 23:18:41 +0000 (08:18 +0900)] 
Use correct type for catalog_xmin

Commit 85c17f6 mistakenly declared a variable storing catalog_xmin as
XLogRecPtr, even though catalog_xmin is a TransactionId.

This caused no functional issue, but the type was clearly incorrect.
Therefore, this commit fixes it to use the correct type TransactionId
instead, and backpatch to v17 where the issue was introduced.

Author: Imran Zaheer <imran.zhir@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CA+UBfa=mNeLt-4BFjEP4tqdDsnq+oMqqPr7fd9Wji2_9YXmQdA@mail.gmail.com

5 weeks agoGuard against uninitialized default locale.
Jeff Davis [Mon, 8 Jun 2026 20:10:40 +0000 (13:10 -0700)] 
Guard against uninitialized default locale.

No known problem today, but defend against issues like dbf217c1c7 in
the future.

Discussion: https://postgr.es/m/d080287d8d2d14c246c86be2e9eb611fb6b27b11.camel@j-davis.com
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Backpatch-through: 17

5 weeks agoRemove inappropriate translation marker in getObjectIdentityParts().
Tom Lane [Mon, 8 Jun 2026 19:23:48 +0000 (15:23 -0400)] 
Remove inappropriate translation marker in getObjectIdentityParts().

Strings built by this function are not supposed to be subject to
NLS translation, but commit 6566133c5 missed that memo, so that
object identities like "membership of role %s in role %s" were
translated.

5 weeks agodict_synonym.c: remove incorrect outlen.
Jeff Davis [Mon, 8 Jun 2026 18:47:40 +0000 (11:47 -0700)] 
dict_synonym.c: remove incorrect outlen.

Previously, outlen was miscalculated if case_sensitive was false and
str_tolower() changed the byte length of the string. If outlen was too
large, pnstrdup() would stop at the NUL terminator, preventing
overrun. But if outlen was too small, it would cause truncation.

Fix by just removing outlen. It was only used in a single site, which
could just as well use pstrdup().

Discussion: https://postgre.es/m/1101e1a3afbbabb503317069c40374b82e6f4cac.camel@j-davis.com
Reviewed-by: Tristan Partin <tristan@partin.io>
Backpatch-through: 14

5 weeks agoFix missed checks for hashability of container-type equality.
Tom Lane [Mon, 8 Jun 2026 15:48:07 +0000 (11:48 -0400)] 
Fix missed checks for hashability of container-type equality.

The operators for array_eq, record_eq, range_eq, and multirange_eq
are all marked oprcanhash, but there's a pitfall: their hash functions
can fail at runtime if the contained type(s) are not hashable.
Therefore, the planner has to check hashability of the contained types
before deciding it can use hashing in these cases.  Not every place
had gotten this memo, and noplace at all had considered the issue
for ranges or multiranges.  In particular we could attempt to use
hashing for a ScalarArrayOpExpr on a container type when it won't
actually work, leading to "could not identify a hash function ..."
runtime failures.

For the most part we should fix this in the lookup functions provided
by lsyscache.c, to wit get_op_hash_functions and op_hashjoinable.
But there's a problem: get_op_hash_functions is not passed the input
data type it would need to check.  We mustn't change the API of that
exported function in a back-patched fix, and even if we wanted to,
its call sites in the executor mostly don't have easy access to the
required data type OID.  Fortunately, the executor call sites don't
actually need fixing, because it's expected that the planner verified
hashability before building a plan that requires it.  Therefore,
leave get_op_hash_functions as-is and invent a wrapper function
get_op_hash_functions_ext that does the additional checking needed
in the planner's uses.

We also need to fix hash_ok_operator (extending the fix in 647889667).

While at it, neaten up a couple of places in lookup_type_cache where
relevant code for multirange cases was written differently from the
code for other container types.

Note: while this touches pg_operator.dat, it's only to add oid_symbol
macros.  So there's no on-disk data change and no need for a
catversion bump.

Reported-by: Andrei Lepikhov <lepihov@gmail.com>
Author: Andrei Lepikhov <lepihov@gmail.com>
Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/ed221f95-f09b-4a9c-b05b-e1fed621ec87@gmail.com
Backpatch-through: 14

5 weeks agodoc: Expand on proper use of refint.
Nathan Bossart [Mon, 8 Jun 2026 15:33:52 +0000 (10:33 -0500)] 
doc: Expand on proper use of refint.

The security team has received a couple of reports about potential
SQL injection via refint's trigger arguments.  We discussed this
while preparing CVE-2026-6637 and concluded that forcibly quoting
these arguments is more likely to break working code than to
prevent exploits.  Unlike data values, the table/column names come
from trigger arguments, and there is little reason for a trigger
author to put hostile inputs into those arguments.  So, let's
document it accordingly.

Reported-by: Nikolay Samokhvalov <nik@postgres.ai>
Reported-by: Alex Young <alex000young@gmail.com>
Reported-by: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Suggested-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com>
Reviewed-by: Christoph Berg <myon@debian.org>
Reviewed-by: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Discussion: https://postgr.es/m/ahXP7z7nsfGPOZ3T%40nathan
Backpatch-through: 14

5 weeks agoecpg: Reject multiple header items in GET/SET DESCRIPTOR
Fujii Masao [Mon, 8 Jun 2026 08:07:48 +0000 (17:07 +0900)] 
ecpg: Reject multiple header items in GET/SET DESCRIPTOR

Previously, ecpg accepted multiple descriptor header items in GET DESCRIPTOR
and SET DESCRIPTOR, but generated broken C code when they were used.
Although the grammar allowed this syntax, the implementation did not actually
support it.

This commit tightens the ecpg grammar so the header form of GET/SET DESCRIPTOR
accepts only a single header item, matching the implementation and preventing
generation of broken C code.

Also update the documentation synopsis accordingly.

Backpatch to all supported versions.

Author: Masashi Kamura <kamura.masashi@fujitsu.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Lakshmi G <lakshmigcdac@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/OS9PR01MB13174AD7D1829D0644B6BB90E9447A@OS9PR01MB13174.jpnprd01.prod.outlook.com
Backpatch-through: 14

5 weeks agoFix memory leak in pgstat_progress_parallel_incr_param()
Michael Paquier [Mon, 8 Jun 2026 06:29:19 +0000 (15:29 +0900)] 
Fix memory leak in pgstat_progress_parallel_incr_param()

When called from a parallel worker, this function calls initStringInfo()
and pq_beginmessage(), causing a StringInfo allocation to happen twice.
pq_endmessage() frees only the second allocation, with each call leaking
~1 kB into the per-worker memory context.  This could cause a few
hundred megabytes worth of memory to pile up until the worker exits (the
message allocations happen in the parallel worker context), with the
situation being worse the longer a parallel worker runs.

Oversight in f1889729dd3.

Author: Baji Shaik <baji.pgdev@gmail.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Tristan Partin <tristan@partin.io>
Discussion: https://postgr.es/m/CA+fm-RMopta1Dmq8udiU5sp+zwTvhUf4+xfbr3rZDfczH+p-xw@mail.gmail.com
Backpatch-through: 17

5 weeks agopsql: Fix expanded aligned output
Michael Paquier [Mon, 8 Jun 2026 05:37:56 +0000 (14:37 +0900)] 
psql: Fix expanded aligned output

When a table's columns are narrower than the record header line, the
expanded aligned format produced misaligned output because the data
column width was not adjusted to match the record header width, leading
to output like:
+-[ RECORD 1 ]-+
| a | 10 |
| b | 20 |
+---+----+

This commit adjusts the output so as the column width match with the
header line, giving:
+-[ RECORD 1 ]-+
| a | 10       |
| b | 20       |
+---+----------+

Author: Pavel Stehule <pavel.stehule@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAFj8pRCzGpsr9zTHbtTd4mGh2YPJqOEgLgt8JLiopuYA9_1xGw@mail.gmail.com
Backpatch-through: 14

5 weeks agopg_surgery: Fix off-by-one bug with heap offset
Michael Paquier [Fri, 5 Jun 2026 23:16:40 +0000 (08:16 +0900)] 
pg_surgery: Fix off-by-one bug with heap offset

heap_force_common() declared a boolean array indexed with an
OffsetNumber for a size of MaxHeapTuplesPerPage.  OffsetNumbers are
1-based, so an input TID whose offset number equals MaxHeapTuplesPerPage
wrote one byte past the end of the stack array, crashing the server.

Like heapam_handler.c, this commit changes the array so as it uses a
0-based index, substracting one from the OffsetNumbers.

Reported-by: Wang Yuelin <violin0613@tju.edu.cn>
Reviewed-by: Ashutosh Sharma <ashu.coek88@gmail.com>
Discussion: https://postgr.es/m/20260604002256.40f1fd544@smtp.qiye.163.com
Backpatch-through: 14

5 weeks agodoc: Use groups instead of curves in TLS documentation
Daniel Gustafsson [Fri, 5 Jun 2026 20:16:42 +0000 (22:16 +0200)] 
doc: Use groups instead of curves in TLS documentation

With TLS 1.3 the concept of curves was renamed to groups.  Update
our wording to use groups instead of curves to make it clear what
the underlying GUC can support.

This was extracted from a slightly larger patch which also renamed
variables to match the new terminology.  Given that we are in beta
this portion was however left as a future excercise.

Author: Evan Si <evsi@amazon.com>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Discussion: https://postgr.es/m/23C40DD6-1C47-46FC-A746-8A1D8530AD3E@amazon.com
Backpatch-through: 18

5 weeks agorefint: Remove plan cache.
Nathan Bossart [Fri, 5 Jun 2026 17:08:05 +0000 (12:08 -0500)] 
refint: Remove plan cache.

Presently, refint stores plans in a per-backend cache to avoid
re-preparing in each call.  This has a few problems.  For one,
check_foreign_key() embeds the new key values in its cascade-UPDATE
queries, so a cached plan reuses the values from preparation.
Also, the cache is never invalidated, so it can return stale
entries that cause other problems.  There may very well be more
bugs lurking.

We could spend a lot of time trying to address all these problems,
but this module is primarily intended as sample code, and by all
indications, it sees minimal use.  Furthermore, there is a growing
consensus for removing refint in v20.  However, since we'll need to
support it on the back-branches for a while longer, it probably
still makes sense to fix some of the more egregious bugs.

Therefore, let's just remove refint's plan cache entirely.  That
means we'll re-prepare on every call, but that seems quite unlikely
to bother anyone.  On v17 and older versions, the regression test
for triggers fails after this change, so I've borrowed pieces of
commit 8cfbdf8f4d to fix it.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/CAJTYsWXU%2BfhuzrEd_bnrxyGH3%2Bny8QRQC2QHf3ws6s9iki3c2Q%40mail.gmail.com
Backpatch-through: 14

5 weeks agoFix off-by-one with NFC recomposition for Hangul U+11A7 (TBASE)
Michael Paquier [Thu, 4 Jun 2026 22:50:12 +0000 (07:50 +0900)] 
Fix off-by-one with NFC recomposition for Hangul U+11A7 (TBASE)

The NFC recomposition incorrectly included TBASE as a valid T syllable,
which is incorrect based on the Unicode specification (TBASE is one
below the start of the range, range beginning at U+11A8).

This would cause the TBASE to be silently swallowed in the
normalization, leading to an incorrect result.

A couple of regression tests are added to check more patterns with
Hangul recomposition and decomposition, on top of a test to check the
problem with TBASE.  Diego has submitted the code fix, and I have
written the tests.

Author: Diego Frias <mail@dzfrias.dev>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/B92ED640-7D4A-4505-B09F-3548F58CBB16@dzfrias.dev
Backpatch-through: 14

5 weeks agoImprove reporting of invalid weight symbols in setweight() et al.
Tom Lane [Thu, 4 Jun 2026 16:24:51 +0000 (12:24 -0400)] 
Improve reporting of invalid weight symbols in setweight() et al.

This commit addresses two related issues:

tsvector_filter() assumed it could print an incorrect weight value
with %c.  This could result in an invalidly-encoded error message
if the database encoding is multibyte and the char value has its
high bit set.  Weight values that are ASCII control characters
could render illegibly too.  Fix by printing such values in octal
(\ooo), similarly to how charout() would render them.

tsvector_setweight() and tsvector_setweight_by_filter() reported
the same unrecognized-weight error condition with elog(), as though
it were an internal error.  That'd not translate, would produce an
unwanted XX000 SQLSTATE code, and also reported the bad value as a
decimal integer which seems unhelpful.  Fix by refactoring so that
all three functions share one copy of the code that interprets a
weight argument.

The invalid-encoding aspect seems to me (tgl) to justify
back-patching.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHNaeLAUzRCXL5AmXLcXaSE_gWAVjWQRmLzc_oZ=1_Vf4Q@mail.gmail.com
Backpatch-through: 14

5 weeks agoFix another case of indirectly casting away const.
Tom Lane [Thu, 4 Jun 2026 15:37:43 +0000 (11:37 -0400)] 
Fix another case of indirectly casting away const.

Like 8f1791c61, this fixes a case of implicitly casting away
const by not treating the result of strrchr() on a const pointer
as const.  This was missed at the time because the machines
reporting those warnings weren't building with --with-llvm.

While here, clean up another infelicity: in the probably-
impossible case that the input string contains only one dot,
this function would call pnstrdup() with a length of -1
and thereby emit a module name equal to the function name.
It seems to me we should emit modname = NULL instead.

Also remove a useless Assert and two redundant assignments.

Back-patch, as 8f1791c61 was, so that users of back branches
don't see this warning when building with late-model gcc.

Reported-by: hubert depesz lubaczewski <depesz@depesz.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/aiGNJ89PBqvq2Yyz@depesz.com
Backpatch-through: 14

6 weeks agopg_dump: scope indAttNames per index in getIndexes()
Alexander Korotkov [Wed, 3 Jun 2026 08:33:35 +0000 (11:33 +0300)] 
pg_dump: scope indAttNames per index in getIndexes()

getIndexes() declared indAttNames and nindAttNames in the outer
per-table loop, so the names collected for an index on expressions
were carried over to the next plain index in the same table.

This is an internal inconsistency rather than a user-facing bug.
dumpRelationStats_dumper() only walks indexes that have pg_statistic
rows, and ANALYZE only creates those for indexes with expressions,
so the second index in the affected pair is not visited and the stale
array is never consulted.

Fix by moving the two variables into the inner per-index loop so each
iteration starts with a clean slate.

Author: Maksim Melnikov <m.melnikov@postgrespro.ru>
Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
Discussion: https://postgr.es/m/be5fc489-587e-421f-bbb8-adb43cfd50f4@postgrespro.ru
Backpatch-through: 17

6 weeks agoFix race in ReplicationSlotRelease() for ephemeral slots
Fujii Masao [Wed, 3 Jun 2026 09:46:49 +0000 (18:46 +0900)] 
Fix race in ReplicationSlotRelease() for ephemeral slots

When releasing an ephemeral replication slot, ReplicationSlotRelease()
drops the slot via ReplicationSlotDropAcquired().

However, after dropping the slot, ReplicationSlotRelease() continued
to use its local "slot" pointer, which still referenced the dropped
slot's former shared-memory entry. It could then update fields such as
effective_xmin in that entry.

Once an ephemeral slot has been dropped (via ReplicationSlotDropAcquired()),
its slot array entry can be reused immediately by another backend
creating a new slot. As a result, those updates could corrupt
the state of an unrelated replication slot.

Fix by skipping those shared-memory updates for phemeral slots and
performing them only for non-ephemeral slots, whose shared-memory
entries remain valid after release.

Backpatch to all supported versions.

Author: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Masao Fujii <masao.fujii@gmail.com>
Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Discussion: https://postgr.es/m/TY4PR01MB177184FF9EE916F577E1F554194082@TY4PR01MB17718.jpnprd01.prod.outlook.com
Backpatch-through: 14

6 weeks agoFix copy-paste error in hash_record_extended()
Michael Paquier [Wed, 3 Jun 2026 03:47:26 +0000 (12:47 +0900)] 
Fix copy-paste error in hash_record_extended()

The code failed to initialize the second isnull argument passed to
FunctionCallInvoke().  This is harmless for existing in-core extended
hash support functions, since FunctionCallInvoke() does not use the
value (note that all the in-core extended hash functions are strict),
examining only the argument values.  However, extension-provided
extended hash functions could be affected if they inspect
PG_ARGISNULL(1).

Oversight in 01e658fa74cb.

Author: Man Zeng <zengman@halodbtech.com>
Discussion: https://postgr.es/m/tencent_7818173C01E01836109848C3@qq.com
Backpatch-through: 14

6 weeks agoFix wrong unsafe-flag test in check_output_expressions()
Richard Guo [Wed, 3 Jun 2026 00:36:52 +0000 (09:36 +0900)] 
Fix wrong unsafe-flag test in check_output_expressions()

The check for window functions (point 4) guarded on the wrong bit: it
tested UNSAFE_NOTIN_DISTINCTON_CLAUSE while setting
UNSAFE_NOTIN_PARTITIONBY_CLAUSE.  Each check in this loop guards on
the same bit it is about to set, as an idempotency optimization, since
unsafeFlags[] is accumulated across the arms of a set operation and
there is no point recomputing a column's status once its bit is
present.

This is not a live bug.  When UNSAFE_NOTIN_PARTITIONBY_CLAUSE is
already set but UNSAFE_NOTIN_DISTINCTON_CLAUSE is not, the guard fails
to skip targetIsInAllPartitionLists() and recomputes it, but setting
the same bit again changes nothing.  When
UNSAFE_NOTIN_DISTINCTON_CLAUSE is already set, point 4 is skipped and
UNSAFE_NOTIN_PARTITIONBY_CLAUSE is left unset; but such a column is
already unsafe for pushdown via UNSAFE_NOTIN_DISTINCTON_CLAUSE, so the
outcome is unchanged.

To fix, test UNSAFE_NOTIN_PARTITIONBY_CLAUSE, matching the bit being
set and the pattern of the surrounding checks.

Back-patch to v15, where the buggy check was introduced.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/CAMbWs49Q_xnF_P2QSUyDzJ34MnrO7dh-cUAaK2HJPgSgh88NcA@mail.gmail.com
Backpatch-through: 15

6 weeks agopsql: Fix issues with deferred errors in pipelines
Michael Paquier [Tue, 2 Jun 2026 23:58:29 +0000 (08:58 +0900)] 
psql: Fix issues with deferred errors in pipelines

When an error is raised while processing a Sync message in a pipeline,
like a deferred constraint violation, the error was not associated with
the piped command and was not counted in available_results.  This caused
assertion failures in discardAbortedPipelineResults(), keeping an
incorrect state at pipeline exit, because the code assumed that the
number of available and requested results would always be positive,
expecting all the counters to be 0 at the end of a pipeline.

This commit switches discardAbortedPipelineResults() and
ExecQueryAndProcessResults() to take a softer approach when consuming
and draining the results after an error.  If there are still piped syncs
in the pipeline when it ends, we now attempt to consume them before
leaving the pipeline mode.

Alexander has been able to reach two assertion failures through his
testing.  While investigating more this issue, I have bumped into two
more.  Most of these cases are covered by the regression tests added in
this commit, plus some cases with mixes of pipelines, deferred errors
and results fetched.  Some of the tests discussed (like the backend
termination one) could not be included in this commit but have been
tested manually.  Another test scenario discussed involved the injection
of an error state in the backend, that was able to trick libpq
internally and put its queue out of sync.  This scenario is not going to
happen in practice, but if we were to do something about it we would
need to make libpq understand that it needs to fail in some cases but
not block.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/19494-97a86d84fee71c47@postgresql.org
Backpatch-through: 18

6 weeks agodoc: Correct the timeline for OAuth's shutdown_cb
Jacob Champion [Fri, 29 May 2026 21:39:03 +0000 (14:39 -0700)] 
doc: Correct the timeline for OAuth's shutdown_cb

During original feature development, the OAuth validator shutdown
callback was invoked via before_shmem_exit(). That was changed to use a
reset callback before commit, but I forgot to update the documentation
for validator developers.

Correct this and backport to 18, where OAuth was introduced. The
callback is invoked whenever the server is "finished" with token
validation. (We make no stronger guarantees here, in the hopes that this
API might successfully navigate future multifactor authentication
support and/or changes to the server threading model.)

Reported-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAN4CZFOuMb_gnLvCwRdMybg_k8WRNJTjcij%2BPoQkuQHDUzxGWg%40mail.gmail.com
Backpatch-through: 18

6 weeks agoUse term "referenced" rather than "dependent" in dependency locking
Heikki Linnakangas [Thu, 28 May 2026 18:27:50 +0000 (21:27 +0300)] 
Use term "referenced" rather than "dependent" in dependency locking

Reported-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Discussion: https://www.postgresql.org/message-id/20260528.114608.488039299811669368.horikyota.ntt@gmail.com
Backpatch-through: 14

6 weeks agoMake stack depth check work with asan's use-after-return
Andres Freund [Thu, 28 May 2026 15:34:11 +0000 (11:34 -0400)] 
Make stack depth check work with asan's use-after-return

With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.

We started using __builtin_frame_address() with de447bb8e6fb, however as of
that commit we just used it for the stack base address, not for the value to
compare to the base address.  Now we use it for both.

When building without __builtin_frame_address() support, we continue to use
stack variables for the stack depth determination.

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/2kk4z4odvuyrg7qlwjd7ft4eron4cle4btb33v4qatgsdkayir@gj6e62rgsel4
Backpatch-through: 14

6 weeks agopostgres_fdw, dblink: Validate use_scram_passthrough values
Fujii Masao [Thu, 28 May 2026 11:58:45 +0000 (20:58 +0900)] 
postgres_fdw, dblink: Validate use_scram_passthrough values

The use_scram_passthrough option in postgres_fdw and dblink accepts
only boolean values. However, unlike other boolean options such as
keep_connections, its value was not previously validated.

As a result, commands such as
"CREATE SERVER ... OPTIONS (use_scram_passthrough 'invalid')"
could succeed unexpectedly.

This commit updates postgres_fdw and dblink to validate that
use_scram_passthrough is assigned a valid boolean value, and throw an
error for invalid input.

Backpatch to v18, where use_scram_passthrough was introduced.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwF+-k-Ehsu5W94ZP7GxS3wiBd+mi0PfGTdJ_i2Yr0zR3g@mail.gmail.com
Backpatch-through: 18

6 weeks agoFix race between ProcSignalInit() and EmitProcSignalBarrier().
Masahiko Sawada [Wed, 27 May 2026 23:25:59 +0000 (16:25 -0700)] 
Fix race between ProcSignalInit() and EmitProcSignalBarrier().

Previously, ProcSignalInit() read the global barrier generation before
publishing its PID into pss_pid. This created a race condition: a
process could initialize its local generation with an older global
value, while a concurrent EmitProcSignalBarrier() might skip that
process because its pss_pid was still zero. This resulted in
WaitForProcSignalBarrier() hanging indefinitely.

Fix this by publishing pss_pid before reading psh_barrierGeneration
with a memory barrier so that the store to pss_pid is ordered before
the load. A concurrent EmitProcSignalBarrier() then either observes
the published PID and signals this slot, or completes its generation
increment before we load it.

While this race has become more visible due to recent features using
signal barriers in more places (such as online wal_level changes), the
issue is theoretically present since signal barriers were introduced
to release smgr caches (e.g., in DROP DATABASE). v14 has the
procsiangl barrier infrastricutre but no in-tree caller that actually
emits a barrier, so the case is unreachable there.

This issue was also reported by buildfarm member flaviventris.

Reported-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Alexander Lakhin <exclusion@gmail.com>
Reviewed-by: Matthias van de Meent <boekewurm+postgres@gmail.com>
Discussion: https://postgr.es/m/CAEze2WgAJmWReDN7Chtba8Er2YBvKCoa0KVN25-1evnTrHsLyA@mail.gmail.com
Backpatch-through: 15

7 weeks agoAvoid orphaned objects dependencies
Heikki Linnakangas [Wed, 27 May 2026 15:35:58 +0000 (18:35 +0300)] 
Avoid orphaned objects dependencies

Concurrent DDL can leave behind objects referencing other objects that
no longer exist. This can happen if an object is dropped, while a new
object that depends on it is created concurrently. For example:

session 1: BEGIN; CREATE FUNCTION myschema.myfunc() ...;
session 2: DROP SCHEMA myschema;
session 1: COMMIT;

DROP SCHEMA does check that there are no objects dependending on the
schema being dropped, but it does not see objects being concurrently
created by other sessions. Even if it did, this scenario would still
fail:

session 1: BEGIN: DROP SCHEMA myschema;
session 2: CREATE FUNCTION myschema.myfunc() ...;
session 1: COMMIT;

When the DROP SCHEMA runs, the schema was empty, but the new function
is created in it before the dropping transaction completes. The CREATE
FUNCTION does not see that the schema is concurrently being dropped.

In both of these scenarios, the function is left behind in the schema
that no longer exists.

To fix, acquire AccessShareLock on all referenced objects when
recording dependencies. This conflicts with the AccessExclusiveLock
taken by DROP, preventing the race. After acquiring the lock, verify
that the object still exists, and if it was dropped concurrently,
report an error. We already had such a mechanism for shared
dependencies, but for some reason we didn't do it for in-database
dependendies.

Ideally the locks would be acquired much earlier when creating a new
object, but that will require modifying a lot of callers. This check
while recording the dependency is a nice wholesale protection, and
even if we change all the CREATE commands to acquire locks earlier,
it's still good to have this as a backstop to catch any cases where we
forgot to do so.

The patch adds a few tests for some cases that left behind orphaned
objects before this. It also adds a test for roles, which already had
such protection, although that test is partially disabled because the
error message includes an OID which is not predictable.

Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Discussion: https://postgr.es/m/ZiYjn0eVc7pxVY45@ip-10-97-1-34.eu-west-3.compute.internal
Backpatch-through: 14

7 weeks agoDon't try to record dependency on a dropped column's datatype
Heikki Linnakangas [Wed, 27 May 2026 15:35:55 +0000 (18:35 +0300)] 
Don't try to record dependency on a dropped column's datatype

When creating a relation with a dropped column, we called
recordDependencyOn() also on the datatype of the dropped column, which
is always InvalidOid. In versions 15 and above, that was harmless
because recordDependencyOn() considers InvalidOid as a pinned object,
and skips over it. On version 14, isPinnedObject() does not consider
InvalidOid as pinned, so we created a bogus pg_depend entry with
refobjectid == 0.

As far as I can tell, the only case when AddNewAttributeTuples() is
called with dropped columns is when performing a table-rewriting ALTER
TABLE command. That temporarily creates a new relation with the same
columns, including dropped ones, then swaps the relations, and drops
the newly created table again. So even on version 14, the bogus
pg_depend entry was only on the transient relation that was dropped at
the end of the ALTER TABLE command, which was harmless.

Even though this is harmless, let's be tidy, similar to commit
713bce9484. The reason I noticed this now and why I backported this,
is because the next commit will add code to acquire locks on the
referenced objects, and we don't want to acquire a lock on InvalidOid.

Discussion: https://postgr.es/m/ZiYjn0eVc7pxVY45@ip-10-97-1-34.eu-west-3.compute.internal
Backpatch-through: 14

7 weeks agoFix procLatch ownership race in ProcKill()
Michael Paquier [Wed, 27 May 2026 08:19:53 +0000 (17:19 +0900)] 
Fix procLatch ownership race in ProcKill()

DisownLatch() was executed after the PGPROC entry of the process
terminated is pushed back into a freelist.  A newly-forked backend that
recycles the slot could call OwnLatch() and PANIC with a "latch already
owned by PID", taking down the server.

There were two scenarios related to lock groups where this issue could
be reached:
* A follower pushes the leader's PGPROC back to the freelist while the
leader has not yet called DisownLatch() in its own ProcKill().
* A leader outliving all its followers pushes its own PGPROC onto the
freelist before reaching DisownLatch(), which would be the most common
scenario.

This issue is fixed by calling SwitchBackToLocalLatch() and
DisownLatch() at an earlier phase of ProcKill(), before any freelist
manipulation happens, so that the slot of the backend terminated is
never exposed as owning a latch.

Note that pgstat_reset_wait_event_storage() is kept at a later stage.
An upcoming commit will take advantage of that by introducing a test
able to check the original PANIC scenario.

Author: Vlad Lesin <vladlesin@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/d2983796-2603-41b7-a66e-fc8489ddb954@gmail.com
Backpatch-through: 14

7 weeks agoFix race conditions in ProcKill()'s lock-group freelist handling
Michael Paquier [Wed, 27 May 2026 05:48:59 +0000 (14:48 +0900)] 
Fix race conditions in ProcKill()'s lock-group freelist handling

This commit fixes two bugs in ProcKill()'s lock-group teardown freelist
publication:
* a double push of the leader's PGPROC that corrupts the freelist.
* a leak of the last follower's PGPROC slot.

ProcKill()'s lock-group teardown had two PGPROC freelist updates
scattered through the function, done under two separate freeProcsLock
acquisitions:
* A follower's push of the leader's PGPROC, done when a follower is the
last group member exiting.
* Every backend's self-push at the bottom of the function.

The two freelist updates were coordinated only by inspecting
proc->lockGroupLeader, which a follower could clear as a side effect of
pushing the leader.  This coordination was broken.  For example, with
two concurrent backends:
* The follower clears leader->lockGroupLeader and pushes the leader's
PGPROC under leader_lwlock.
* The follower does not clear its own proc->lockGroupLeader, being
skipped.
* When the leader reaches the bottom of ProcKill(), it sees a NULL
proc->lockGroupLeader (the follower cleared it) and pushes itself,
causing a second dlist_push_tail() of the same node onto the same
freelist.
* The follower at the bottom sees its own proc->lockGroupLeader being
not NULL (never cleared) and skips its own push, causing its own slot
to leak.

This commit refactors the freelist manipulation to be done in two
distinct phases, each step using its own lock acquisition to ensure that
each freelist operation happens in an isolated manner for each backend
(follower or leader):
- First, under a single leader_lwlock acquisition, check the state of
the lock-group.  Depending on if we are dealing with a follower and/or a
leader, and if the leader has exited before a follower, then set some
state booleans that define which actions should be taken with the
freelist.
- Second, under a single freeProcsLock acquisition, perform the cleanup
actions, self-push of a backend and/or push of the leader back to the
freelist.

This is an old issue, dating back to 9.6 where parallel workers and lock
grouping has been added.

Author: Vlad Lesin <vladlesin@gmail.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/d2983796-2603-41b7-a66e-fc8489ddb954@gmail.com
Backpatch-through: 14

7 weeks agopg_createsubscriber: Fix cleanup of publisher-side objects after errors
Fujii Masao [Wed, 27 May 2026 01:35:18 +0000 (10:35 +0900)] 
pg_createsubscriber: Fix cleanup of publisher-side objects after errors

When pg_createsubscriber fails after creating logical replication
objects, it should remove the publication and replication slot that
it created on the publisher.

Previously, if dropping subscriber-side objects failed,
pg_createsubscriber reset its internal cleanup state too early. As a
result, the exit-time cleanup could skip removing the publication or
replication slot on the publisher.

This could leave pg_createsubscriber-created objects behind on
the publisher after a failed run. That can make a retry harder,
because the leftover publication or replication slot may need to be
removed manually before running pg_createsubscriber again.
In the case of a replication slot, leaving it behind can also retain
WAL files longer than expected.

The cause of this issue was that the flags made_publication and
made_replslot tracking whether pg_createsubscriber created
a publication or replication slot on the primary were incorrectly
reset to false when failures occurred while dropping objects
on the subscriber.

This commit fixes the issue by preventing those cleanup flags from
being reset even when failures occurred while dropping objects
on the subscriber, ensuring proper cleanup of primary objects
before exit on failure.

Backpatch to v17, where pg_createsubscriber was added.

Author: Nisha Moond <nisha.moond412@gmail.com>
Reviewed-by: David G. Johnston <david.g.johnston@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Peter Smith <smithpb2250@gmail.com>
Discussion: https://postgr.es/m/CABdArM5V9QKK1PkLY9dpgAcZa3kUp84-wPqPovxvdLOri4=69w@mail.gmail.com
Backpatch-through: 17

7 weeks agoSkip pg_database.dathasloginevt cleanup on standby
Alexander Korotkov [Tue, 26 May 2026 23:26:50 +0000 (02:26 +0300)] 
Skip pg_database.dathasloginevt cleanup on standby

EventTriggerOnLogin() tries to clear pg_database.dathasloginevt when
the database no longer has any login event triggers but the flag is
still set.  To make that safe against concurrent flag setters, it
takes a conditional AccessExclusiveLock on the database object.

On a hot standby, that lock acquisition fails outright with

  FATAL:  cannot acquire lock mode AccessExclusiveLock on database
          objects while recovery is in progress

because LockAcquireExtended() refuses locks stronger than
RowExclusiveLock on database objects during recovery.  The standby
already replays the flag's value from the primary, so the dangling
flag is the result of replaying a state in which the primary had
already dropped its login event triggers but not yet run a login
event trigger pass to clear the flag.  Any session connecting to the
standby in that window therefore fails to connect.

Skip the cleanup on a standby.  The flag will be cleared via WAL
replay once the primary clears it on its side.

Add a recovery TAP test that reproduces the original report: create
and drop a login event trigger on the primary in one session, wait
for the standby to replay, then verify that a fresh connection to
the standby succeeds.

Backpatch to v17, where the login event triggers were introduced.

Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reported-by: Egor Chindyaskin <kyzevan23@mail.ru>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
Discussion: https://postgr.es/m/19488-d7ccfca2bf6b74b0%40postgresql.org
Backpatch-through: 17

7 weeks agoAdd stack depth check to QueueFKConstraintValidation().
Tom Lane [Tue, 26 May 2026 15:58:25 +0000 (11:58 -0400)] 
Add stack depth check to QueueFKConstraintValidation().

QueueFKConstraintValidation() recurses through the partition hierarchy
to queue child constraint validations and to mark child rows as
validated.  With a sufficiently deep partition tree, this can result
in a stack-overflow crash.  Defend against that as we do elsewhere.

Bug: #19482
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19482-4cc37cbf52d55235@postgresql.org
Backpatch-through: 18

7 weeks agoFix missed ReleaseVariableStats() in intarray's _int_matchsel().
Tom Lane [Mon, 25 May 2026 22:15:49 +0000 (18:15 -0400)] 
Fix missed ReleaseVariableStats() in intarray's _int_matchsel().

Given a WHERE clause like "int[] @@ query_int" or "query_int ~~ int[]"
where the query_int side is a table column having statistics,
_int_matchsel() exited without remembering to free the statistics
tuple.  This would typically lead to warnings about cache refcount
leakage, like
  WARNING:  resource was not closed: cache pg_statistic (73), tuple 42/12 has count 1
It's been wrong since this code was added, in commit c6fbe6d6f.

Bug: #19492
Reported-by: Man Zeng <zengman@halodbtech.com>
Author: Man Zeng <zengman@halodbtech.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19492-ddcd0e22399ef85a@postgresql.org
Backpatch-through: 14

7 weeks agodblink: Reject use_scram_passthrough on foreign-data wrappers
Fujii Masao [Mon, 25 May 2026 16:07:24 +0000 (01:07 +0900)] 
dblink: Reject use_scram_passthrough on foreign-data wrappers

Previously, dblink accepted the use_scram_passthrough option on
foreign-data wrappers via ALTER FOREIGN DATA WRAPPER dblink_fdw
OPTIONS, even though the setting had no effect there.

use_scram_passthrough should be only meaningful for foreign servers
and user mappings, so this commit updates dblink to accept the option
only in those contexts.

Backpatch to v18, where use_scram_passthrough was introduced.

Author: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEJ8rZjmbOvCicyr4vbuLio082bNTde0WNoSWaWr9wVcg@mail.gmail.com
Backpatch-through: 18

7 weeks agodblink: Give user mapping precedence for use_scram_passthrough
Fujii Masao [Mon, 25 May 2026 15:51:18 +0000 (00:51 +0900)] 
dblink: Give user mapping precedence for use_scram_passthrough

Commit 97f6fc10fff changed postgres_fdw so that user-mapping settings
override foreign server settings for use_scram_passthrough. This commit
applies the same behavior to dblink.

Backpatch to v18, where use_scram_passthrough was introduced.

Author: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEJ8rZjmbOvCicyr4vbuLio082bNTde0WNoSWaWr9wVcg@mail.gmail.com
Backpatch-through: 18

7 weeks agopostgres_fdw: Give user mapping precedence for use_scram_passthrough
Fujii Masao [Mon, 25 May 2026 15:46:31 +0000 (00:46 +0900)] 
postgres_fdw: Give user mapping precedence for use_scram_passthrough

Previously, when use_scram_passthrough was specified on both a foreign server
and a user mapping, the server-level setting took precedence over the
user-mapping setting. This was inconsistent with the usual semantics of
postgres_fdw options, where foreign server options provide shared defaults
and user mapping options override them on a per-user basis.

This commit updates postgres_fdw so that the user-mapping setting takes
precedence when use_scram_passthrough is specified in both places. This
matches the behavior of other connection options such as sslcert and sslkey.

Backpatch to v18, where use_scram_passthrough was introduced. In v18,
this only affects limited configurations that specify conflicting values
at both the foreign server and user-mapping levels. In such cases, users
would naturally expect the user-mapping setting to override the server-level
setting, so changing the behavior should be minimally disruptive.
Also keeping v18 as the only branch with different semantics for
use_scram_passthrough would be unnecessarily confusing, so backpatch
this fix to v18.

Author: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEJ8rZjmbOvCicyr4vbuLio082bNTde0WNoSWaWr9wVcg@mail.gmail.com
Backpatch-through: 18

7 weeks agoFix size check in statext_dependencies_deserialize()
Michael Paquier [Mon, 25 May 2026 05:38:59 +0000 (14:38 +0900)] 
Fix size check in statext_dependencies_deserialize()

The check for the minimum expected bytea size of a MVDependencies object
was using SizeOfItem() for its calculation.  This macro uses the number
of attributes in a single dependency.

This minimum size calculation should be based on MinSizeOfItems(), that
computes the minimum expected size as the header plus the
minimally-sized number of dependency items.

Oversight in d08c44f7a4ec.

Author: Ilia Evdokimov <ilya.evdokimov@tantorlabs.com>
Discussion: https://postgr.es/m/4b8d299d-2505-4c30-bf80-0f697410db35@tantorlabs.com
Backpatch-through: 14

7 weeks agoAvoid exposing WAL receiver raw conninfo during timeline jumps
Michael Paquier [Fri, 22 May 2026 23:10:12 +0000 (08:10 +0900)] 
Avoid exposing WAL receiver raw conninfo during timeline jumps

When reusing an existing WAL receiver after it has reached
WALRCV_WAITING for new instructions, RequestXLogStreaming() copied
PrimaryConnInfo into WalRcv->conninfo before switching the state to
WALRCV_RESTARTING.  At that point ready_to_display could still be true,
so pg_stat_wal_receiver could expose the raw connection string,
including sensitive fields, but it should only show the user-displayable
version of the connection string.

WALRCV_RESTARTING does not establish a new connection.  The waiting WAL
receiver reuses its existing connection and only needs a new startpoint
and timeline, so there is no need to copy the raw connection string into
shared memory again.  Let's only copy conninfo when launching a new WAL
receiver after WALRCV_STOPPED, not while waiting for instructions.

This commit adds coverage for the case fixed by this commit to the
timeline-switch test by verifying that the WAL receiver conninfo remains
consistent across the jump.

Backpatch all the way down, as this issue is possible since
pg_stat_wal_receiver has been introduced.

Author: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/EF91FF76-1E2B-4F3B-9162-290B4DC517FF@gmail.com
Backpatch-through: 14

7 weeks agoPrevent setting NO INHERIT on partitioned NOT NULL constraints
Fujii Masao [Fri, 22 May 2026 14:59:04 +0000 (23:59 +0900)] 
Prevent setting NO INHERIT on partitioned NOT NULL constraints

The documentation states that NOT NULL constraints on partitioned tables
are always inherited by all partitions, and therefore cannot be declared
NO INHERIT. While a check already existed to reject creating such
constraints with NO INHERIT, previously the same check was missing for
ALTER TABLE ... ALTER CONSTRAINT ... NO INHERIT.

This commit adds the missing check so that attempting to set NO INHERIT
on a partitioned NOT NULL constraint now fails.

Backpatch to v18, where ALTER TABLE ... ALTER CONSTRAINT ... [NO] INHERIT
was added.

Author: Andreas Karlsson <andreas@proxel.se>
Reviewed-by: Jim Jones <jim.jones@uni-muenster.de>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/ecc985ad-6ec1-4094-a315-317943ca5f3f@proxel.se
Backpatch-through: 18

8 weeks agopg_recvlogical: Honor source cluster file permissions for output files
Fujii Masao [Wed, 20 May 2026 06:54:13 +0000 (15:54 +0900)] 
pg_recvlogical: Honor source cluster file permissions for output files

Commit c37b3d08ca6 attempted to preserve group permissions on pg_recvlogical
output files when group access was enabled on the source cluster. However,
the output files were still created with a fixed S_IRUSR | S_IWUSR mode,
preventing group-read permissions from being applied.

This commit fixes the issue by creating output files with pg_file_create_mode
instead of a hard-coded mode. This allows pg_recvlogical to correctly preserve
group permissions from the source cluster.

Backpatch to all supported branches.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Srinath Reddy Sadipiralla <srinath2133@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwHhpizYzMo3nFP4GkNMueSNMY3QfC-gBN1VTXtuiANDvw@mail.gmail.com
Backpatch-through: 14

8 weeks agopsql: Make ParseVariableDouble reject values above max
Daniel Gustafsson [Mon, 18 May 2026 15:33:36 +0000 (08:33 -0700)] 
psql: Make ParseVariableDouble reject values above max

ParseVariableDouble missed returning false after logging an error when
the parsed value exceeded max, making the value assigned rather than
rejected.  Backpatch down to v18 where this was introduced as part of
the \WATCH_INTERVAL.

Author: Sven Klemm <sven@tigerdata.com>
Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/CAMCrgp31p_5SDVi7dwnP39tTW5icQ0MWHA+N4kJdXgkL0PEy8w@mail.gmail.com
Backpatch-through: 18

8 weeks agoinjection_points: Move some structs to new header injection_points.h
Michael Paquier [Mon, 18 May 2026 02:11:44 +0000 (11:11 +0900)] 
injection_points: Move some structs to new header injection_points.h

This commit moves the definitions of InjectionPointConditionType and
InjectionPointCondition into a new header local to the test module
injection_points.h, so as these can be shared across more files in the
module.  A patch for a bug fix is under discussion, whose proposed test
will benefit from this refactoring.

Backpatch down to where the module exists, as this should be useful for
future bug fixes, even cases unrelated to the thread where this change
has been discussed.

Author: Andrey Borodin <x4mmm@yandex-team.ru>
Author: Vlad Lesin <vladlesin@gmail.com>
Discussion: https://postgr.es/m/d2983796-2603-41b7-a66e-fc8489ddb954@gmail.com
Backpatch-through: 17

8 weeks agoUse ereport(ERROR), not Assert(), for publisher tuples missing columns.
Noah Misch [Sun, 17 May 2026 01:01:35 +0000 (18:01 -0700)] 
Use ereport(ERROR), not Assert(), for publisher tuples missing columns.

Three locations use Assert() to guard against a mismatch between the
number of columns advertised in the RELATION message and the number
actually received in the subsequent INSERT/UPDATE tuple message. Since
these values originate from the publisher, the check must survive into
production builds.

A malicious or buggy publisher can send a RELATION claiming N columns
and an INSERT claiming M < N columns. The subscriber's apply worker
indexes into colvalues[]/colstatus[] using column indices from the
RELATION message's attribute map, causing a heap out-of-bounds read when
the tuple's column array is smaller than expected. We've looked, without
success, for a scenario in which the publisher holds sufficient control
over these out-of-bounds bytes to exploit this or even to reach a
SIGSEGV. Despite not finding one, the code has been fragile. Back-patch
to v14 (all supported versions).

Reported-by: Varik Matevosyan <varikmatevosyan@gmail.com>
Author: Varik Matevosyan <varikmatevosyan@gmail.com>
Discussion: https://postgr.es/m/CA+bBoog3cCogktzfLb9bppUByu-10B3CFp8u=iKXG_OvtAguCw@mail.gmail.com
Backpatch-through: 14

8 weeks agoDoc: fix release-note typo.
Tom Lane [Fri, 15 May 2026 22:32:33 +0000 (18:32 -0400)] 
Doc: fix release-note typo.

This mention of memcpy() should of course have said memcmp().

Reported-by: chris@chrullrich.net
Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/177883653690.764749.14038057906859461991@wrigleys.postgresql.org
Backpatch-through: 14

2 months agoRe-add regression tests for ltree and intarray
Michael Paquier [Fri, 15 May 2026 09:02:47 +0000 (18:02 +0900)] 
Re-add regression tests for ltree and intarray

These tests have been removed by 906ea101d0d5, due to some of them being
unstable in the buildfarm with low max_stack_depth values.  They are now
reworked so as they should be more portable.

The tests to cover the findoprnd() overflows use a balanced tree to
avoid using too much stack, per a suggestion and an investigation by Tom
Lane.

Note: This is initially applied only on HEAD; a backpatch will follow
should the buildfarm be fine with the situation.

Discussion: https://postgr.es/m/agZc6XecyE7E7fep@paquier.xyz
Backpatch-through: 14

2 months agorefint: Fix segfault in check_foreign_key().
Nathan Bossart [Thu, 14 May 2026 18:11:49 +0000 (13:11 -0500)] 
refint: Fix segfault in check_foreign_key().

When an UPDATE statement triggers check_foreign_key() with the
action set to "cascade", it generates more UPDATE statements to
modify the key values in referencing relations.  If a new key value
is NULL, SPI_getvalue() returns a NULL pointer, which is
subsequently passed to quote_literal_cstr(), causing a segfault.
To fix, skip quoting when a new key value is NULL and insert an
unquoted NULL keyword instead.

Oversight in commit 260e97733b.  While the refint documentation
recommends marking primary key columns NOT NULL, the aforementioned
scenario accidentally worked on platforms where snprintf()
substitutes "(null)" for NULL pointers.  Note that for
character-type columns, the old code quoted "(null)" as a string
literal, so this didn't always produce correct results.  But it
still seems better to fix this than to reject cases that previously
worked.

Reported-by: Nikita Kalinin <n.kalinin@postgrespro.ru>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Pierre Forstmann <pierre.forstmann@gmail.com>
Discussion: https://postgr.es/m/19476-bd04ea6241345303%40postgresql.org
Backpatch-through: 14

2 months agoPrevent access to other sessions' temp tables
Alexander Korotkov [Thu, 14 May 2026 09:25:19 +0000 (12:25 +0300)] 
Prevent access to other sessions' temp tables

Commit b7b0f3f2724 ("Use streaming I/O in sequential scans") routed
sequential scans through read_stream_next_buffer(), bypassing the
RELATION_IS_OTHER_TEMP() check in ReadBufferExtended().  As a result,
a superuser can attempt to read or modify temp tables of other
sessions through the read-stream path.  When the query plan uses no index,
SELECT/UPDATE/DELETE/MERGE silently see no rows / report zero affected rows,
and COPY produces an empty output -- because the buffer manager has no
visibility into the owning session's local buffers and silently returns
nothing.  Any query plan that uses, for instance, a btree index
still errors out via the existing check in ReadBufferExtended(), which
is reached from hio.c and nbtree respectively, but this is incidental.

Fix by enforcing RELATION_IS_OTHER_TEMP() at the three additional
buffer-manager entry points:

- read_stream_begin_impl() rejects the read at stream setup time,
  covering sequential and bitmap scans that go through the
  read-stream path.
- ReadBuffer_common() becomes the canonical place for the check,
  consolidating the existing one previously kept in
  ReadBufferExtended().  All ReadBufferExtended() callers go through
  ReadBuffer_common(), so the consolidation is behavior-preserving.
- StartReadBuffersImpl() catches direct callers of StartReadBuffers()
  that bypass both of the above.  This is currently defense-in-depth,
  but documents the contract for future code.

The companion test in src/test/modules/test_misc was added in the
preceding commit; this commit updates the assertions for SELECT,
UPDATE, DELETE, MERGE, and COPY (which previously documented the
bug as silent success) to expect the new error.

Author: Jim Jones <jim.jones@uni-muenster.de>
Author: Daniil Davydov <3danissimo@gmail.com>
Co-authored-by: Alexander Korotkov <aekorotkov@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Soumya S Murali <soumyamurali.work@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAJDiXghdFcZ8%3Dnh4G69te7iRr3Q0uFyXxb3ZdG09_GTNZXwH0g%40mail.gmail.com
Backpatch-through: 17

2 months agoAdd tests for cross-session temp table access
Alexander Korotkov [Thu, 14 May 2026 09:21:03 +0000 (12:21 +0300)] 
Add tests for cross-session temp table access

Add a TAP test in src/test/modules/test_misc that documents what
happens when one session attempts to read or modify another session's
temporary table.  This commit only adds tests; it does not change
backend behavior, so the assertions reflect current behavior:

- SELECT, UPDATE, DELETE, MERGE, COPY on a table without an index
  silently succeed with no error and zero rows / zero affected rows.
  These commands run through the read-stream path, which currently
  bypasses the RELATION_IS_OTHER_TEMP() check.  This is the
  underlying bug to be fixed in a follow-up.
- INSERT errors with "cannot access temporary tables of other
  sessions" because hio.c calls ReadBufferExtended() to find a page
  with free space and is caught by the existing check there.
- Index scan errors via the same existing check, reached through
  nbtree -> ReadBuffer -> ReadBufferExtended.
- TRUNCATE / ALTER TABLE / ALTER INDEX / CLUSTER fail with their
  command-specific error messages.
- VACUUM is silently skipped to avoid noise during database-wide
  VACUUM (vacuum_rel() returns without warning).
- DROP TABLE is intentionally allowed: DROP does not touch the
  table's contents, and autovacuum relies on this to clean up
  temp relations orphaned by a crashed backend.
- ALTER FUNCTION / DROP FUNCTION on an owner-created function over
  its own temp row type work as catalog operations -- they don't
  read the underlying data.
- CREATE FUNCTION from a separate session, using another session's
  temp row type as an argument, is allowed but emits a NOTICE: the
  function is moved into the creator's pg_temp namespace with an
  auto-dependency on the borrowed type, so it disappears together
  with the session that created it.
- A bare DROP TABLE on a temp table that has a cross-session
  dependent function fails with a catalog-level dependency error.
- LOCK TABLE in ACCESS SHARE mode on another session's temp table
  succeeds and properly blocks the owner's session-exit cleanup
  (which acquires AccessExclusiveLock via findDependentObjects).
  This exercises the same LockRelationOid path used by autovacuum
  when cleaning up orphaned temp relations.
- When the owner session ends, the normal session-exit cleanup
  cascades through DEPENDENCY_NORMAL and removes both the temp
  objects and any cross-session functions that depended on them.

Also, document the contract for RELATION_IS_OTHER_TEMP() so that
future buffer-access entry points enforce the same rule.

Backpatch this through PostgreSQL 17, where b7b0f3f27241 introduces a code
path bypassing this check.

Author: Jim Jones <jim.jones@uni-muenster.de>
Author: Daniil Davydov <3danissimo@gmail.com>
Co-authored-by: Alexander Korotkov <aekorotkov@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Soumya S Murali <soumyamurali.work@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAJDiXghdFcZ8%3Dnh4G69te7iRr3Q0uFyXxb3ZdG09_GTNZXwH0g%40mail.gmail.com
Backpatch-through: 17

2 months agopgbench: fix verbose error message corruption with multiple threads
Fujii Masao [Thu, 14 May 2026 03:30:34 +0000 (12:30 +0900)] 
pgbench: fix verbose error message corruption with multiple threads

When pgbench runs with multiple threads and verbose error reporting is
enabled (--verbose-errors), multiple clients can build verbose error
messages concurrently. Previously, a function-local static
PQExpBuffer was used for these messages, causing the buffer to be
shared across threads. This was not thread-safe and could result in
corrupted or incorrect log output.

Fix this by using a local PQExpBufferData instead of a static buffer.
This keeps verbose error messages correct during concurrent execution.

Backpatch to v15, where this issue was introduced.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Alex Guo <guo.alex.hengchen@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwER1AjGXpkKB9t9820NBhMQ_Ghv7=HsKeodUr3=SZsF4g@mail.gmail.com
Backpatch-through: 15

2 months agoAdd more tests for corrupted data with pglz_decompress()
Michael Paquier [Wed, 13 May 2026 05:43:46 +0000 (14:43 +0900)] 
Add more tests for corrupted data with pglz_decompress()

Two cases fixed by 2b5ba2a0a141 were not covered, to emulate the
handling of corrupted data, for:
- set control bit with a valid 2-byte match tag where offset is 0.
- set control bit with a valid 2-byte match tag where offset exceeds
output written.

Oversight in 67d318e70402.

Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/agF4xkIdRcrCIprs@paquier.xyz
Backpatch-through: 14

2 months agoFix stale COPY progress during logical replication table sync
Fujii Masao [Wed, 13 May 2026 02:44:31 +0000 (11:44 +0900)] 
Fix stale COPY progress during logical replication table sync

Previously, pg_stat_progress_copy in the subscriber could continue to show
the initial COPY operation for logical replication table synchronization as
active even after the data copy had finished. The stale progress entry
remained visible until synchronization caught up with the publisher.

This happened because the table synchronization code called BeginCopyFrom()
and CopyFrom(), but failed to call EndCopyFrom() afterward.

This commit fixes the issue by adding the missing EndCopyFrom() call so that
the COPY progress state in the subscriber is cleared as soon as the initial
data copy completes.

Backpatch to all supported branches.

Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: ChangAo Chen <cca5507@qq.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAOzEurQKuy3RiPkd=25PEwEzaqHuGvEOf=X7vaVzhgNjaukYzA@mail.gmail.com
Backpatch-through: 14

2 months agoStamp 18.4. REL_18_4
Tom Lane [Mon, 11 May 2026 19:44:35 +0000 (15:44 -0400)] 
Stamp 18.4.

2 months agoLast-minute updates for release notes.
Tom Lane [Mon, 11 May 2026 18:54:40 +0000 (14:54 -0400)] 
Last-minute updates for release notes.

Security: CVE-2026-6472, CVE-2026-6473, CVE-2026-6474, CVE-2026-6475, CVE-2026-6476, CVE-2026-6477, CVE-2026-6478, CVE-2026-6479, CVE-2026-6575, CVE-2026-6637, CVE-2026-6638

2 months agoUse palloc_array() in a few more places to avoid overflow
Heikki Linnakangas [Mon, 11 May 2026 18:18:06 +0000 (21:18 +0300)] 
Use palloc_array() in a few more places to avoid overflow

These could overflow on 32-bit systems.

Backpatch-through: 14
Security: CVE-2026-6473

2 months agoRemove test cases for field overflows in intarray and ltree.
Tom Lane [Mon, 11 May 2026 16:12:03 +0000 (12:12 -0400)] 
Remove test cases for field overflows in intarray and ltree.

These checks are failing in the buildfarm, reporting stack overflows
rather than the expected errors, though seemingly only on ppc64 and
s390x platforms.  Perhaps there is something off about our tests
for stack depth on those architectures?  But there's no time to
debug that right now, and surely these tests aren't too essential.
Revert for now and plan to revisit after the release dust settles.

Backpatch-through: 14
Security: CVE-2026-6473