diff --git a/contrib/hstore_plpython/hstore_plpython.c b/contrib/hstore_plpython/hstore_plpython.c index 93c39d294dd..93705f0d54c 100644 --- a/contrib/hstore_plpython/hstore_plpython.c +++ b/contrib/hstore_plpython/hstore_plpython.c @@ -128,9 +128,9 @@ Datum plpython_to_hstore(PG_FUNCTION_ARGS) { PyObject *dict; - PyObject *volatile items = NULL; - int32 pcount; - HStore *out; + PyObject *volatile items; + Py_ssize_t pcount; + HStore *volatile out; dict = (PyObject *) PG_GETARG_POINTER(0); if (!PyMapping_Check(dict)) @@ -144,7 +144,7 @@ plpython_to_hstore(PG_FUNCTION_ARGS) PG_TRY(); { int32 buflen; - int32 i; + Py_ssize_t i; Pairs *pairs; pairs = palloc(pcount * sizeof(*pairs)); @@ -176,7 +176,6 @@ plpython_to_hstore(PG_FUNCTION_ARGS) pairs[i].isnull = false; } } - Py_DECREF(items); pcount = hstoreUniquePairs(pairs, pcount, &buflen); out = hstorePairs(pairs, pcount, buflen); @@ -188,5 +187,7 @@ plpython_to_hstore(PG_FUNCTION_ARGS) } PG_END_TRY(); + Py_DECREF(items); + PG_RETURN_POINTER(out); } diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c index 1bc984d5c4d..24e7c6559d6 100644 --- a/contrib/jsonb_plpython/jsonb_plpython.c +++ b/contrib/jsonb_plpython/jsonb_plpython.c @@ -164,56 +164,91 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb) } else { - /* array in v */ + PyObject *volatile elem = NULL; + result = PyList_New(0); if (!result) return NULL; - while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + PG_TRY(); { - if (r == WJB_ELEM) + while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) { - PyObject *elem = PLyObject_FromJsonbValue(&v); + if (r != WJB_ELEM) + continue; + + elem = PLyObject_FromJsonbValue(&v); PyList_Append(result, elem); Py_XDECREF(elem); + elem = NULL; } } + PG_CATCH(); + { + Py_XDECREF(elem); + Py_XDECREF(result); + PG_RE_THROW(); + } + PG_END_TRY(); } break; case WJB_BEGIN_OBJECT: - result = PyDict_New(); - if (!result) - return NULL; - - while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) { - if (r == WJB_KEY) + PyObject *volatile result_v = PyDict_New(); + PyObject *volatile key = NULL; + PyObject *volatile val = NULL; + + if (!result_v) + return NULL; + + PG_TRY(); { - PyObject *key = PLyString_FromJsonbValue(&v); - - if (!key) - return NULL; - - r = JsonbIteratorNext(&it, &v, true); - - if (r == WJB_VALUE) + while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) { - PyObject *value = PLyObject_FromJsonbValue(&v); + if (r != WJB_KEY) + continue; - if (!value) + key = PLyString_FromJsonbValue(&v); + if (!key) { - Py_XDECREF(key); - return NULL; + Py_XDECREF(result_v); + result_v = NULL; + break; } - PyDict_SetItem(result, key, value); - Py_XDECREF(value); - } + if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_VALUE) + elog(ERROR, "unexpected jsonb token: %d", r); - Py_XDECREF(key); + val = PLyObject_FromJsonbValue(&v); + if (!val) + { + Py_XDECREF(key); + key = NULL; + Py_XDECREF(result_v); + result_v = NULL; + break; + } + + PyDict_SetItem(result_v, key, val); + + Py_XDECREF(key); + key = NULL; + Py_XDECREF(val); + val = NULL; + } } + PG_CATCH(); + { + Py_XDECREF(result_v); + Py_XDECREF(key); + Py_XDECREF(val); + PG_RE_THROW(); + } + PG_END_TRY(); + + result = result_v; } break; @@ -234,10 +269,8 @@ static JsonbValue * PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state) { Py_ssize_t pcount; - JsonbValue *out = NULL; - - /* We need it volatile, since we use it after longjmp */ - PyObject *volatile items = NULL; + PyObject *volatile items; + JsonbValue *volatile out; pcount = PyMapping_Size(obj); items = PyMapping_Items(obj); @@ -281,6 +314,8 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state) } PG_END_TRY(); + Py_DECREF(items); + return out; } @@ -295,19 +330,30 @@ PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state) { Py_ssize_t i; Py_ssize_t pcount; + PyObject *volatile value = NULL; pcount = PySequence_Size(obj); pushJsonbValue(jsonb_state, WJB_BEGIN_ARRAY, NULL); - for (i = 0; i < pcount; i++) + PG_TRY(); { - PyObject *value = PySequence_GetItem(obj, i); + for (i = 0; i < pcount; i++) + { + value = PySequence_GetItem(obj, i); + Assert(value); - (void) PLyObject_ToJsonbValue(value, jsonb_state, true); - - Py_XDECREF(value); + (void) PLyObject_ToJsonbValue(value, jsonb_state, true); + Py_XDECREF(value); + value = NULL; + } } + PG_CATCH(); + { + Py_XDECREF(value); + PG_RE_THROW(); + } + PG_END_TRY(); return pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL); }