Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 25826c9

Browse files
committed
Charles Waldman writes:
""" Running "test_extcall" repeatedly results in memory leaks. One of these can't be fixed (at least not easily!), it happens since this code: def saboteur(**kw): kw['x'] = locals() d = {} saboteur(a=1, **d) creates a circular reference - d['x']['d']==d The others are due to some missing decrefs in ceval.c, fixed by the patch attached below. Note: I originally wrote this without the "goto", just adding the missing decref's where needed. But I think the goto is justified in keeping the executable code size of ceval as small as possible. """ [I think the circular reference is more like kw['x']['kw'] == kw. --GvR]
1 parent 5ce78f8 commit 25826c9

1 file changed

Lines changed: 13 additions & 14 deletions

File tree

Python/ceval.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,48 +1623,42 @@ eval_code2(co, globals, locals,
16231623
if (!PyDict_Check(kwdict)) {
16241624
PyErr_SetString(PyExc_TypeError,
16251625
"** argument must be a dictionary");
1626-
x = NULL;
1627-
break;
1626+
goto extcall_fail;
16281627
}
16291628
}
16301629
if (flags & 1) {
16311630
stararg = POP();
16321631
if (!PySequence_Check(stararg)) {
16331632
PyErr_SetString(PyExc_TypeError,
16341633
"* argument must be a sequence");
1635-
x = NULL;
1636-
break;
1634+
goto extcall_fail;
16371635
}
16381636
/* Convert abstract sequence to concrete tuple */
16391637
if (!PyTuple_Check(stararg)) {
16401638
PyObject *t = NULL;
16411639
t = PySequence_Tuple(stararg);
16421640
if (t == NULL) {
1643-
x = NULL;
1644-
break;
1641+
goto extcall_fail;
16451642
}
16461643
Py_DECREF(stararg);
16471644
stararg = t;
16481645
}
16491646
nstar = PyTuple_GET_SIZE(stararg);
16501647
if (nstar < 0) {
1651-
x = NULL;
1652-
break;
1648+
goto extcall_fail;
16531649
}
16541650
}
16551651
if (nk > 0) {
16561652
if (kwdict == NULL) {
16571653
kwdict = PyDict_New();
16581654
if (kwdict == NULL) {
1659-
x = NULL;
1660-
break;
1655+
goto extcall_fail;
16611656
}
16621657
}
16631658
else {
16641659
PyObject *d = PyDict_Copy(kwdict);
16651660
if (d == NULL) {
1666-
x = NULL;
1667-
break;
1661+
goto extcall_fail;
16681662
}
16691663
Py_DECREF(kwdict);
16701664
kwdict = d;
@@ -1680,7 +1674,7 @@ eval_code2(co, globals, locals,
16801674
PyString_AsString(key));
16811675
Py_DECREF(key);
16821676
Py_DECREF(value);
1683-
break;
1677+
goto extcall_fail;
16841678
}
16851679
err = PyDict_SetItem(kwdict, key, value);
16861680
Py_DECREF(key);
@@ -1689,7 +1683,11 @@ eval_code2(co, globals, locals,
16891683
break;
16901684
}
16911685
if (err) {
1692-
Py_DECREF(kwdict);
1686+
extcall_fail:
1687+
Py_XDECREF(kwdict);
1688+
Py_XDECREF(stararg);
1689+
Py_DECREF(func);
1690+
x=NULL;
16931691
break;
16941692
}
16951693
}
@@ -2382,6 +2380,7 @@ PyEval_CallObjectWithKeywords(func, arg, kw)
23822380
if (kw != NULL && !PyDict_Check(kw)) {
23832381
PyErr_SetString(PyExc_TypeError,
23842382
"keyword list must be a dictionary");
2383+
Py_DECREF(arg);
23852384
return NULL;
23862385
}
23872386

0 commit comments

Comments
 (0)