]> granicus.if.org Git - postgresql/commitdiff
Consistently catch errors from Python _New() functions
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 31 Oct 2017 14:49:36 +0000 (10:49 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Sat, 18 Nov 2017 18:39:53 +0000 (13:39 -0500)
Python Py*_New() functions can fail and return NULL in out-of-memory
conditions.  The previous code handled that inconsistently or not at
all.  This change organizes that better.  If we are in a function that
is called from Python, we just check for failure and return NULL
ourselves, which will cause any exception information to be passed up.
If we are called from PostgreSQL, we consistently create an "out of
memory" error.

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
contrib/hstore_plpython/hstore_plpython.c
contrib/ltree_plpython/ltree_plpython.c
src/pl/plpython/plpy_cursorobject.c
src/pl/plpython/plpy_exec.c
src/pl/plpython/plpy_main.c
src/pl/plpython/plpy_plpymodule.c
src/pl/plpython/plpy_procedure.c
src/pl/plpython/plpy_resultobject.c
src/pl/plpython/plpy_spi.c
src/pl/plpython/plpy_typeio.c

index 22366bd40f76c99f3c88a53c2bda6625d0e37105..218e6612b14717cdd8296ab7186838b30a09c6bb 100644 (file)
@@ -93,6 +93,10 @@ hstore_to_plpython(PG_FUNCTION_ARGS)
        PyObject   *dict;
 
        dict = PyDict_New();
+       if (!dict)
+               ereport(ERROR,
+                               (errcode(ERRCODE_OUT_OF_MEMORY),
+                                errmsg("out of memory")));
 
        for (i = 0; i < count; i++)
        {
index ae9b90dd10b03dccba7e8dda5a011fce66d67a65..e88636a0a965c26ab6c2a3861513b54770bf0133 100644 (file)
@@ -46,6 +46,10 @@ ltree_to_plpython(PG_FUNCTION_ARGS)
        ltree_level *curlevel;
 
        list = PyList_New(in->numlevel);
+       if (!list)
+               ereport(ERROR,
+                               (errcode(ERRCODE_OUT_OF_MEMORY),
+                                errmsg("out of memory")));
 
        curlevel = LTREE_FIRST(in);
        for (i = 0; i < in->numlevel; i++)
index 10ca786fbc2426cad04e8e27f6a6248da67b15bb..9467f648082dbffd92dd35578d694cb0df1778e8 100644 (file)
@@ -457,17 +457,24 @@ PLy_cursor_fetch(PyObject *self, PyObject *args)
 
                        Py_DECREF(ret->rows);
                        ret->rows = PyList_New(SPI_processed);
-
-                       PLy_input_setup_tuple(&cursor->result, SPI_tuptable->tupdesc,
-                                                                 exec_ctx->curr_proc);
-
-                       for (i = 0; i < SPI_processed; i++)
+                       if (!ret->rows)
                        {
-                               PyObject   *row = PLy_input_from_tuple(&cursor->result,
-                                                                                                          SPI_tuptable->vals[i],
-                                                                                                          SPI_tuptable->tupdesc);
+                               Py_DECREF(ret);
+                               ret = NULL;
+                       }
+                       else
+                       {
+                               PLy_input_setup_tuple(&cursor->result, SPI_tuptable->tupdesc,
+                                                                         exec_ctx->curr_proc);
+
+                               for (i = 0; i < SPI_processed; i++)
+                               {
+                                       PyObject   *row = PLy_input_from_tuple(&cursor->result,
+                                                                                                                  SPI_tuptable->vals[i],
+                                                                                                                  SPI_tuptable->tupdesc);
 
-                               PyList_SetItem(ret->rows, i, row);
+                                       PyList_SetItem(ret->rows, i, row);
+                               }
                        }
                }
 
index 02d7d2ad5f8eda8e3872177375939dec1dd0f9cc..9d2341a4a3b4c166c4717872f1dd73ab58fd5330 100644 (file)
@@ -420,6 +420,9 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
        PG_TRY();
        {
                args = PyList_New(proc->nargs);
+               if (!args)
+                       return NULL;
+
                for (i = 0; i < proc->nargs; i++)
                {
                        PLyDatumToOb *arginfo = &proc->args[i];
@@ -693,7 +696,7 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
        {
                pltdata = PyDict_New();
                if (!pltdata)
-                       PLy_elog(ERROR, "could not create new dictionary while building trigger arguments");
+                       return NULL;
 
                pltname = PyString_FromString(tdata->tg_trigger->tgname);
                PyDict_SetItemString(pltdata, "name", pltname);
@@ -826,6 +829,11 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
                        PyObject   *pltarg;
 
                        pltargs = PyList_New(tdata->tg_trigger->tgnargs);
+                       if (!pltargs)
+                       {
+                               Py_DECREF(pltdata);
+                               return NULL;
+                       }
                        for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
                        {
                                pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
index 29db90e4489f3edb3cc2d4feb276671749f55a89..32d23ae5b6d0883fd1d29bdeae6016087bc7ac95 100644 (file)
@@ -167,7 +167,7 @@ PLy_init_interp(void)
        PLy_interp_globals = PyModule_GetDict(mainmod);
        PLy_interp_safe_globals = PyDict_New();
        if (PLy_interp_safe_globals == NULL)
-               PLy_elog(ERROR, "could not create globals");
+               PLy_elog(ERROR, NULL);
        PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
        Py_DECREF(mainmod);
        if (PLy_interp_globals == NULL || PyErr_Occurred())
index 759ad449323caeb0c866c03967fda33c6dbdc722..23f99e20ca35780a53c60b32d3dd41a0c98da5c6 100644 (file)
@@ -233,7 +233,7 @@ PLy_create_exception(char *name, PyObject *base, PyObject *dict,
 
        exc = PyErr_NewException(name, base, dict);
        if (exc == NULL)
-               PLy_elog(ERROR, "could not create exception \"%s\"", name);
+               PLy_elog(ERROR, NULL);
 
        /*
         * PyModule_AddObject does not add a refcount to the object, for some odd
@@ -268,7 +268,7 @@ PLy_generate_spi_exceptions(PyObject *mod, PyObject *base)
                PyObject   *dict = PyDict_New();
 
                if (dict == NULL)
-                       PLy_elog(ERROR, "could not generate SPI exceptions");
+                       PLy_elog(ERROR, NULL);
 
                sqlstate = PyString_FromString(unpack_sql_state(exception_map[i].sqlstate));
                if (sqlstate == NULL)
index 58d6988202557b20366fe0053f97ea5c14292067..faa4977463a2796f8e147b658884f3aa6a9a1641 100644 (file)
@@ -368,6 +368,8 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src)
         * all functions
         */
        proc->statics = PyDict_New();
+       if (!proc->statics)
+               PLy_elog(ERROR, NULL);
        PyDict_SetItemString(proc->globals, "SD", proc->statics);
 
        /*
index 098a366f6fa72ba123a6823ce2fc3363fd7a3c44..ca70e256892cf2ff7455bb1287f979ebcdabfefd 100644 (file)
@@ -112,6 +112,11 @@ PLy_result_new(void)
        ob->nrows = PyInt_FromLong(-1);
        ob->rows = PyList_New(0);
        ob->tupdesc = NULL;
+       if (!ob->rows)
+       {
+               Py_DECREF(ob);
+               return NULL;
+       }
 
        return (PyObject *) ob;
 }
@@ -147,6 +152,8 @@ PLy_result_colnames(PyObject *self, PyObject *unused)
        }
 
        list = PyList_New(ob->tupdesc->natts);
+       if (!list)
+               return NULL;
        for (i = 0; i < ob->tupdesc->natts; i++)
        {
                Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
@@ -171,6 +178,8 @@ PLy_result_coltypes(PyObject *self, PyObject *unused)
        }
 
        list = PyList_New(ob->tupdesc->natts);
+       if (!list)
+               return NULL;
        for (i = 0; i < ob->tupdesc->natts; i++)
        {
                Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
@@ -195,6 +204,8 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused)
        }
 
        list = PyList_New(ob->tupdesc->natts);
+       if (!list)
+               return NULL;
        for (i = 0; i < ob->tupdesc->natts; i++)
        {
                Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
index 69eb6b39f67ec66f1f21501a816cb5f34330fbd1..ade27f3924210b2f8a622762e53ade0f4ad0f64f 100644 (file)
@@ -360,6 +360,8 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status)
        volatile MemoryContext oldcontext;
 
        result = (PLyResultObject *) PLy_result_new();
+       if (!result)
+               return NULL;
        Py_DECREF(result->status);
        result->status = PyInt_FromLong(status);
 
@@ -409,17 +411,24 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status)
 
                                Py_DECREF(result->rows);
                                result->rows = PyList_New(rows);
-
-                               PLy_input_setup_tuple(&ininfo, tuptable->tupdesc,
-                                                                         exec_ctx->curr_proc);
-
-                               for (i = 0; i < rows; i++)
+                               if (!result->rows)
                                {
-                                       PyObject   *row = PLy_input_from_tuple(&ininfo,
-                                                                                                                  tuptable->vals[i],
-                                                                                                                  tuptable->tupdesc);
+                                       Py_DECREF(result);
+                                       result = NULL;
+                               }
+                               else
+                               {
+                                       PLy_input_setup_tuple(&ininfo, tuptable->tupdesc,
+                                                                                 exec_ctx->curr_proc);
+
+                                       for (i = 0; i < rows; i++)
+                                       {
+                                               PyObject   *row = PLy_input_from_tuple(&ininfo,
+                                                                                                                          tuptable->vals[i],
+                                                                                                                          tuptable->tupdesc);
 
-                                       PyList_SetItem(result->rows, i, row);
+                                               PyList_SetItem(result->rows, i, row);
+                                       }
                                }
                        }
 
index ce1527072e4d008c0c8b49c1ecf6f57aa6680bfa..c48e8fd5f3b67ede264da76c609d6cee6c7eae5d 100644 (file)
@@ -718,6 +718,8 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
        PyObject   *list;
 
        list = PyList_New(dims[dim]);
+       if (!list)
+               return NULL;
 
        if (dim < ndim - 1)
        {
@@ -826,7 +828,7 @@ PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
 
        dict = PyDict_New();
        if (dict == NULL)
-               PLy_elog(ERROR, "could not create new dictionary");
+               return NULL;
 
        PG_TRY();
        {