Skip to content

Commit 57d0051

Browse files
Move return statements out of PG_TRY blocks.
If we exit a PG_TRY block early via "continue", "break", "goto", or "return", we'll skip unwinding its exception stack. This change moves a couple of such "return" statements in PL/Python out of PG_TRY blocks. This was introduced in d0aa965 and affects all supported versions. We might also be able to add compile-time checks to prevent recurrence, but that is left as a future exercise. Reported-by: Mikhail Gribkov, Xing Guo Author: Xing Guo Reviewed-by: Michael Paquier, Andres Freund, Tom Lane Discussion: https://postgr.es/m/CAMEv5_v5Y%2B-D%3DCO1%2Bqoe16sAmgC4sbbQjz%2BUtcHmB6zcgS%2B5Ew%40mail.gmail.com Discussion: https://postgr.es/m/CACpMh%2BCMsGMRKFzFMm3bYTzQmMU5nfEEoEDU2apJcc4hid36AQ%40mail.gmail.com Backpatch-through: 11 (all supported versions)
1 parent f75cec4 commit 57d0051

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

src/pl/plpython/plpy_exec.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,20 @@ static PyObject *
411411
PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
412412
{
413413
PyObject *volatile arg = NULL;
414-
PyObject *volatile args = NULL;
414+
PyObject *args;
415415
int i;
416416

417+
/*
418+
* Make any Py*_New() calls before the PG_TRY block so that we can quickly
419+
* return NULL on failure. We can't return within the PG_TRY block, else
420+
* we'd miss unwinding the exception stack.
421+
*/
422+
args = PyList_New(proc->nargs);
423+
if (!args)
424+
return NULL;
425+
417426
PG_TRY();
418427
{
419-
args = PyList_New(proc->nargs);
420-
if (!args)
421-
return NULL;
422-
423428
for (i = 0; i < proc->nargs; i++)
424429
{
425430
PLyDatumToOb *arginfo = &proc->args[i];
@@ -683,19 +688,34 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
683688
*pltlevel,
684689
*pltrelid,
685690
*plttablename,
686-
*plttableschema;
687-
PyObject *pltargs,
691+
*plttableschema,
692+
*pltargs = NULL,
688693
*pytnew,
689-
*pytold;
690-
PyObject *volatile pltdata = NULL;
694+
*pytold,
695+
*pltdata;
691696
char *stroid;
692697

693-
PG_TRY();
698+
/*
699+
* Make any Py*_New() calls before the PG_TRY block so that we can quickly
700+
* return NULL on failure. We can't return within the PG_TRY block, else
701+
* we'd miss unwinding the exception stack.
702+
*/
703+
pltdata = PyDict_New();
704+
if (!pltdata)
705+
return NULL;
706+
707+
if (tdata->tg_trigger->tgnargs)
694708
{
695-
pltdata = PyDict_New();
696-
if (!pltdata)
709+
pltargs = PyList_New(tdata->tg_trigger->tgnargs);
710+
if (!pltargs)
711+
{
712+
Py_DECREF(pltdata);
697713
return NULL;
714+
}
715+
}
698716

717+
PG_TRY();
718+
{
699719
pltname = PLyUnicode_FromString(tdata->tg_trigger->tgname);
700720
PyDict_SetItemString(pltdata, "name", pltname);
701721
Py_DECREF(pltname);
@@ -835,12 +855,9 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
835855
int i;
836856
PyObject *pltarg;
837857

838-
pltargs = PyList_New(tdata->tg_trigger->tgnargs);
839-
if (!pltargs)
840-
{
841-
Py_DECREF(pltdata);
842-
return NULL;
843-
}
858+
/* pltargs should have been allocated before the PG_TRY block. */
859+
Assert(pltargs);
860+
844861
for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
845862
{
846863
pltarg = PLyUnicode_FromString(tdata->tg_trigger->tgargs[i]);
@@ -861,6 +878,7 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
861878
}
862879
PG_CATCH();
863880
{
881+
Py_XDECREF(pltargs);
864882
Py_XDECREF(pltdata);
865883
PG_RE_THROW();
866884
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy