postgresql/src/tools
Tom Lane 9bcb8a694b plpython: Use funccache.c infrastructure for procedure caching.
PL/Python set-returning functions can crash with a use-after-free when
CREATE OR REPLACE FUNCTION is executed while the SRF is mid-iteration.
The crash occurs because srfstate->savedargs is allocated in proc->mcxt,
which gets deleted when the procedure is invalidated, leaving a dangling
pointer that PLy_function_restore_args() then dereferences.

The best fix is to use reference counting to prevent destroying the
function state while it's still in use, similar to what PL/pgSQL has
done.  Rather than inventing a new wheel, this commit converts
PL/Python to use the funccache.c infrastructure.

The main challenge is that PL/Python uses SFRM_ValuePerCall for SRFs,
where the handler is called multiple times.  A naive implementation
would allow the refcount to return to zero between calls, but we need
to hang onto the original state and function body.  SQL-language
functions face the same challenge, so this commit follows the same
approach used in functions.c: maintain a per-call-site cache struct
(PLyProcedureCache) in fn_extra that holds both the pointer to the
long-lived PLyProcedure and the SRF execution state.

The use_count is incremented when we first obtain the procedure and is
decremented via a MemoryContextCallback registered on fn_mcxt, which runs
even during error aborts. Cleaning up the per-call SRF state needs more
care: an ExprContextCallback handles the in-query cases, since the
iterator is not guaranteed to run to completion (for example a LIMIT or a
rescan can abandon it early). But unlike SQL functions, whose resources
are released by transaction abort, PL/Python holds Python reference counts
on the iterator and saved arguments that abort will not release, and
ExprContextCallbacks are not invoked during an error abort. The
MemoryContextCallback on fn_mcxt therefore doubles as the backstop that
releases those references when a query errors out mid-iteration.

Since fn_extra is now used for PLyProcedureCache, this commit removes
use of the funcapi.h SRF infrastructure (SRF_IS_FIRSTCALL,
SRF_RETURN_NEXT, etc.) and switches to direct isDone signaling via
ReturnSetInfo, matching how SQL functions handle ValuePerCall mode.

This fixes a longstanding bug, so ideally we'd back-patch it.  But
it'd be impractical to back-patch further than v18 where funccache.c
came in.  The patch is somewhat invasive, and the bug only arises in
very uncommon usages (which is why it evaded detection for so long).
On the whole, the risk/reward ratio for putting this into v18 doesn't
seem good, so commit to master only.

Bug: #19480
Reported-by: Andrzej Doros <adoros@starfishstorage.com>
Author: Matheus Alcantara <matheusssilv97@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19480-f1f9fdce30462fc4@postgresql.org
2026-06-21 15:08:27 -04:00
..
ci ci: Improve ccache handling 2026-06-08 15:26:47 -04:00
editors Make Emacs perl-mode indent more like perltidy. 2019-01-13 11:32:31 -08:00
ifaddrs Update copyright for 2026 2026-01-01 13:24:10 -05:00
perlcheck Use "grep -E" not "egrep". 2026-05-13 12:07:19 -04:00
pg_bsd_indent Modernize pg_bsd_indent's error/warning reporting code. 2026-06-15 12:22:55 -04:00
pginclude libpq: Split PGOAUTHDEBUG=UNSAFE into multiple options 2026-04-07 08:15:14 -07:00
pgindent plpython: Use funccache.c infrastructure for procedure caching. 2026-06-21 15:08:27 -04:00
add_commit_links.pl Pre-beta mechanical code beautification, step 2: run pgperltidy. 2026-05-13 10:37:42 -04:00
ccsym tools/ccsym: update for modern versions of gcc 2015-01-20 13:02:58 -05:00
check_bison_recursion.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00
copyright.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00
darwin_sysroot Move darwin sysroot determination into separate file 2022-09-01 16:54:19 -07:00
find_badmacros Remove cvs keywords from all files. 2010-09-20 22:08:53 +02:00
find_meson meson: Add initial version of meson based build system 2022-09-21 22:37:17 -07:00
find_static Fix trap in a few shell scripts 2022-09-20 18:50:16 +02:00
find_typedef Use "grep -E" not "egrep". 2026-05-13 12:07:19 -04:00
gen_export.pl Restore AIX support. 2026-02-23 13:34:22 -05:00
gen_keywordlist.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00
generate_editorconfig.py Add script to keep .editorconfig in sync with .gitattributes 2025-02-01 10:09:45 +01:00
git-external-diff Preserve information on use of git-external-diff 2018-05-24 23:45:31 +09:30
git_changelog Update copyright for 2026 2026-01-01 13:24:10 -05:00
install_files meson: make install_test_files more generic, rename to install_files 2023-03-23 21:20:18 -07:00
make_ctags Fix make_etags breakage on certain platforms. 2023-06-14 11:02:50 +09:00
make_etags Fix make_etags failure on Mac. 2023-02-15 09:52:42 +09:00
make_mkid Add another pgdefine path check, and a cvs-git change. 2011-08-26 21:52:35 -04:00
mark_pgdllimport.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00
msvc_gendef.pl MSVC: Support building for AArch64. 2026-01-07 13:42:57 -06:00
PerfectHash.pm Update copyright for 2026 2026-01-01 13:24:10 -05:00
pgflex pgflex: propagate environment to flex subprocess 2025-06-30 12:24:48 +02:00
pgtest pgtest: fix spacing 2023-08-14 14:03:29 -04:00
rcgen meson: Add windows resource files 2022-10-05 09:56:05 -07:00
RELEASE_CHANGES Remove gen_node_support.pl's ad-hoc ABI stability check. 2026-04-21 10:58:00 -04:00
testwrap Add 'make check-tests' behavior to the meson based builds 2025-11-21 17:12:22 -05:00
valgrind.supp Fix typos and inconsistencies in code and comments 2026-01-05 09:19:15 +09:00
version_stamp.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00
win32tzlist.pl Update copyright for 2026 2026-01-01 13:24:10 -05:00