Skip to content

Commit 52c9cf3

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 d5de344 commit 52c9cf3

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
@@ -415,15 +415,20 @@ static PyObject *
415415
PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
416416
{
417417
PyObject *volatile arg = NULL;
418-
PyObject *volatile args = NULL;
418+
PyObject *args;
419419
int i;
420420

421+
/*
422+
* Make any Py*_New() calls before the PG_TRY block so that we can quickly
423+
* return NULL on failure. We can't return within the PG_TRY block, else
424+
* we'd miss unwinding the exception stack.
425+
*/
426+
args = PyList_New(proc->nargs);
427+
if (!args)
428+
return NULL;
429+
421430
PG_TRY();
422431
{
423-
args = PyList_New(proc->nargs);
424-
if (!args)
425-
return NULL;
426-
427432
for (i = 0; i < proc->nargs; i++)
428433
{
429434
PLyDatumToOb *arginfo = &proc->args[i];
@@ -687,19 +692,34 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
687692
*pltlevel,
688693
*pltrelid,
689694
*plttablename,
690-
*plttableschema;
691-
PyObject *pltargs,
695+
*plttableschema,
696+
*pltargs = NULL,
692697
*pytnew,
693-
*pytold;
694-
PyObject *volatile pltdata = NULL;
698+
*pytold,
699+
*pltdata;
695700
char *stroid;
696701

697-
PG_TRY();
702+
/*
703+
* Make any Py*_New() calls before the PG_TRY block so that we can quickly
704+
* return NULL on failure. We can't return within the PG_TRY block, else
705+
* we'd miss unwinding the exception stack.
706+
*/
707+
pltdata = PyDict_New();
708+
if (!pltdata)
709+
return NULL;
710+
711+
if (tdata->tg_trigger->tgnargs)
698712
{
699-
pltdata = PyDict_New();
700-
if (!pltdata)
713+
pltargs = PyList_New(tdata->tg_trigger->tgnargs);
714+
if (!pltargs)
715+
{
716+
Py_DECREF(pltdata);
701717
return NULL;
718+
}
719+
}
702720

721+
PG_TRY();
722+
{
703723
pltname = PyString_FromString(tdata->tg_trigger->tgname);
704724
PyDict_SetItemString(pltdata, "name", pltname);
705725
Py_DECREF(pltname);
@@ -839,12 +859,9 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
839859
int i;
840860
PyObject *pltarg;
841861

842-
pltargs = PyList_New(tdata->tg_trigger->tgnargs);
843-
if (!pltargs)
844-
{
845-
Py_DECREF(pltdata);
846-
return NULL;
847-
}
862+
/* pltargs should have been allocated before the PG_TRY block. */
863+
Assert(pltargs);
864+
848865
for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
849866
{
850867
pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
@@ -865,6 +882,7 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
865882
}
866883
PG_CATCH();
867884
{
885+
Py_XDECREF(pltargs);
868886
Py_XDECREF(pltdata);
869887
PG_RE_THROW();
870888
}

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