Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e360f0

Browse files
committed
Avoid Python memory leaks in hstore_plpython and jsonb_plpython.
Fix some places where we might fail to do Py_DECREF() on a Pythonobject (thereby leaking it for the rest of the session). Almostall of the risks were in error-recovery paths, which we don't reallyexpect to hit anyway. Hence, while this is definitely a bug fix,it doesn't quite seem worth back-patching.Nikita Glukhov, Michael Paquier, Tom LaneDiscussion:https://postgr.es/m/28053a7d-10d8-fc23-b05c-b4749c873f63@postgrespro.ru
1 parent46e3442 commit9e360f0

File tree

2 files changed

+83
-36
lines changed

2 files changed

+83
-36
lines changed

‎contrib/hstore_plpython/hstore_plpython.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ Datum
128128
plpython_to_hstore(PG_FUNCTION_ARGS)
129129
{
130130
PyObject*dict;
131-
PyObject*volatileitems=NULL;
132-
int32pcount;
133-
HStore*out;
131+
PyObject*volatileitems;
132+
Py_ssize_tpcount;
133+
HStore*volatileout;
134134

135135
dict= (PyObject*)PG_GETARG_POINTER(0);
136136
if (!PyMapping_Check(dict))
@@ -144,7 +144,7 @@ plpython_to_hstore(PG_FUNCTION_ARGS)
144144
PG_TRY();
145145
{
146146
int32buflen;
147-
int32i;
147+
Py_ssize_ti;
148148
Pairs*pairs;
149149

150150
pairs=palloc(pcount*sizeof(*pairs));
@@ -176,7 +176,6 @@ plpython_to_hstore(PG_FUNCTION_ARGS)
176176
pairs[i].isnull= false;
177177
}
178178
}
179-
Py_DECREF(items);
180179

181180
pcount=hstoreUniquePairs(pairs,pcount,&buflen);
182181
out=hstorePairs(pairs,pcount,buflen);
@@ -188,5 +187,7 @@ plpython_to_hstore(PG_FUNCTION_ARGS)
188187
}
189188
PG_END_TRY();
190189

190+
Py_DECREF(items);
191+
191192
PG_RETURN_POINTER(out);
192193
}

‎contrib/jsonb_plpython/jsonb_plpython.c

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -164,56 +164,91 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
164164
}
165165
else
166166
{
167-
/* array in v */
167+
PyObject*volatileelem=NULL;
168+
168169
result=PyList_New(0);
169170
if (!result)
170171
returnNULL;
171172

172-
while ((r=JsonbIteratorNext(&it,&v, true))!=WJB_DONE)
173+
PG_TRY();
173174
{
174-
if (r==WJB_ELEM)
175+
while ((r=JsonbIteratorNext(&it,&v, true))!=WJB_DONE)
175176
{
176-
PyObject*elem=PLyObject_FromJsonbValue(&v);
177+
if (r!=WJB_ELEM)
178+
continue;
179+
180+
elem=PLyObject_FromJsonbValue(&v);
177181

178182
PyList_Append(result,elem);
179183
Py_XDECREF(elem);
184+
elem=NULL;
180185
}
181186
}
187+
PG_CATCH();
188+
{
189+
Py_XDECREF(elem);
190+
Py_XDECREF(result);
191+
PG_RE_THROW();
192+
}
193+
PG_END_TRY();
182194
}
183195
break;
184196

185197
caseWJB_BEGIN_OBJECT:
186-
result=PyDict_New();
187-
if (!result)
188-
returnNULL;
189-
190-
while ((r=JsonbIteratorNext(&it,&v, true))!=WJB_DONE)
191198
{
192-
if (r==WJB_KEY)
193-
{
194-
PyObject*key=PLyString_FromJsonbValue(&v);
199+
PyObject*volatileresult_v=PyDict_New();
200+
PyObject*volatilekey=NULL;
201+
PyObject*volatileval=NULL;
195202

196-
if (!key)
197-
returnNULL;
198-
199-
r=JsonbIteratorNext(&it,&v, true);
203+
if (!result_v)
204+
returnNULL;
200205

201-
if (r==WJB_VALUE)
206+
PG_TRY();
207+
{
208+
while ((r=JsonbIteratorNext(&it,&v, true))!=WJB_DONE)
202209
{
203-
PyObject*value=PLyObject_FromJsonbValue(&v);
210+
if (r!=WJB_KEY)
211+
continue;
204212

205-
if (!value)
213+
key=PLyString_FromJsonbValue(&v);
214+
if (!key)
215+
{
216+
Py_XDECREF(result_v);
217+
result_v=NULL;
218+
break;
219+
}
220+
221+
if ((r=JsonbIteratorNext(&it,&v, true))!=WJB_VALUE)
222+
elog(ERROR,"unexpected jsonb token: %d",r);
223+
224+
val=PLyObject_FromJsonbValue(&v);
225+
if (!val)
206226
{
207227
Py_XDECREF(key);
208-
returnNULL;
228+
key=NULL;
229+
Py_XDECREF(result_v);
230+
result_v=NULL;
231+
break;
209232
}
210233

211-
PyDict_SetItem(result,key,value);
212-
Py_XDECREF(value);
213-
}
234+
PyDict_SetItem(result_v,key,val);
214235

236+
Py_XDECREF(key);
237+
key=NULL;
238+
Py_XDECREF(val);
239+
val=NULL;
240+
}
241+
}
242+
PG_CATCH();
243+
{
244+
Py_XDECREF(result_v);
215245
Py_XDECREF(key);
246+
Py_XDECREF(val);
247+
PG_RE_THROW();
216248
}
249+
PG_END_TRY();
250+
251+
result=result_v;
217252
}
218253
break;
219254

@@ -234,10 +269,8 @@ static JsonbValue *
234269
PLyMapping_ToJsonbValue(PyObject*obj,JsonbParseState**jsonb_state)
235270
{
236271
Py_ssize_tpcount;
237-
JsonbValue*out=NULL;
238-
239-
/* We need it volatile, since we use it after longjmp */
240-
PyObject*volatileitems=NULL;
272+
PyObject*volatileitems;
273+
JsonbValue*volatileout;
241274

242275
pcount=PyMapping_Size(obj);
243276
items=PyMapping_Items(obj);
@@ -281,6 +314,8 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
281314
}
282315
PG_END_TRY();
283316

317+
Py_DECREF(items);
318+
284319
returnout;
285320
}
286321

@@ -295,19 +330,30 @@ PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
295330
{
296331
Py_ssize_ti;
297332
Py_ssize_tpcount;
333+
PyObject*volatilevalue=NULL;
298334

299335
pcount=PySequence_Size(obj);
300336

301337
pushJsonbValue(jsonb_state,WJB_BEGIN_ARRAY,NULL);
302338

303-
for (i=0;i<pcount;i++)
339+
PG_TRY();
304340
{
305-
PyObject*value=PySequence_GetItem(obj,i);
306-
307-
(void)PLyObject_ToJsonbValue(value,jsonb_state, true);
341+
for (i=0;i<pcount;i++)
342+
{
343+
value=PySequence_GetItem(obj,i);
344+
Assert(value);
308345

346+
(void)PLyObject_ToJsonbValue(value,jsonb_state, true);
347+
Py_XDECREF(value);
348+
value=NULL;
349+
}
350+
}
351+
PG_CATCH();
352+
{
309353
Py_XDECREF(value);
354+
PG_RE_THROW();
310355
}
356+
PG_END_TRY();
311357

312358
returnpushJsonbValue(jsonb_state,WJB_END_ARRAY,NULL);
313359
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp