0001-plpython-Use-correct-memory-context-for-savedargs.patch

text/plain

Filename: 0001-plpython-Use-correct-memory-context-for-savedargs.patch
Type: text/plain
Part: 0
Message: Re: BUG #19480: PL/Python SRF crashes (SIGSEGV) when function is replaced mid-iteration: use-after-free in PLy_funct

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch 0001
Subject: plpython: Use correct memory context for savedargs
File+
src/pl/plpython/plpy_exec.c 20 7
From 61f46abd4509cc519de3e43adfd9e0b4fa0f6fcb Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <mths.dev@pm.me>
Date: Mon, 25 May 2026 19:22:09 -0300
Subject: [PATCH] plpython: Use correct memory context for savedargs

---
 src/pl/plpython/plpy_exec.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index de0dad1f533..d93e800e0be 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -31,7 +31,7 @@ typedef struct PLySRFState
 } PLySRFState;
 
 static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc);
-static PLySavedArgs *PLy_function_save_args(PLyProcedure *proc);
+static PLySavedArgs *PLy_function_save_args(MemoryContext mctx, PLyProcedure *proc);
 static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs);
 static void PLy_function_drop_args(PLySavedArgs *savedargs);
 static void PLy_global_args_push(PLyProcedure *proc);
@@ -176,8 +176,15 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
 				 * This won't be last call, so save argument values.  We do
 				 * this again each time in case the iterator is changing those
 				 * values.
+				 *
+				 * We use funcctx->multi_call_memory_ctx to ensure savedargs
+				 * survives across ValuePerCall invocations, but is cleaned up
+				 * when the SRF completes.  This also protects against the
+				 * case where the procedure is delated (via
+				 * PLy_procedure_delete ) while the SRF is running.
 				 */
-				srfstate->savedargs = PLy_function_save_args(proc);
+				srfstate->savedargs = PLy_function_save_args(funcctx->multi_call_memory_ctx,
+															 proc);
 			}
 		}
 
@@ -536,13 +543,13 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
  * available via the proc's globals :-( ... but we're stuck with that now.
  */
 static PLySavedArgs *
-PLy_function_save_args(PLyProcedure *proc)
+PLy_function_save_args(MemoryContext mctx, PLyProcedure *proc)
 {
 	PLySavedArgs *result;
 
-	/* saved args are always allocated in procedure's context */
+	/* Allocate in the caller-specified memory context */
 	result = (PLySavedArgs *)
-		MemoryContextAllocZero(proc->mcxt,
+		MemoryContextAllocZero(mctx,
 							   offsetof(PLySavedArgs, namedargs) +
 							   proc->nargs * sizeof(PyObject *));
 	result->nargs = proc->nargs;
@@ -658,8 +665,14 @@ PLy_global_args_push(PLyProcedure *proc)
 	{
 		PLySavedArgs *node;
 
-		/* Build a struct containing current argument values */
-		node = PLy_function_save_args(proc);
+		/*
+		 * Build a struct containing current argument values.  We use
+		 * proc->mcxt because the saved args must persist across the entire
+		 * recursive call stack, which can span multiple function invocations.
+		 * The procedure's memory context has the appropriate lifetime for
+		 * this, and we explicitly free the struct when popping.
+		 */
+		node = PLy_function_save_args(proc->mcxt, proc);
 
 		/*
 		 * Push the saved argument values into the procedure's stack.  Once we
-- 
2.50.1 (Apple Git-155)