mirror of https://github.com/python/cpython.git
Fix #2702, with a correct accounting of recursion.
This commit is contained in:
parent
1e022689b7
commit
763d309bba
|
@ -94,23 +94,19 @@ class Node(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class cPickleDeepRecursive(unittest.TestCase):
|
class cPickleDeepRecursive(unittest.TestCase):
|
||||||
# I commented out, because the patch that fixes this was reverted, as
|
def test_issue2702(self):
|
||||||
# it broke the next test case. Check the issues for full history.
|
# This should raise a RecursionLimit but in some
|
||||||
# def test_issue2702(self):
|
# platforms (FreeBSD, win32) sometimes raises KeyError instead,
|
||||||
# '''This should raise a RecursionLimit but in some
|
# or just silently terminates the interpreter (=crashes).
|
||||||
# platforms (FreeBSD, win32) sometimes raises KeyError instead,
|
nodes = [Node() for i in range(500)]
|
||||||
# or just silently terminates the interpreter (=crashes).
|
for n in nodes:
|
||||||
# '''
|
n.connections = list(nodes)
|
||||||
# nodes = [Node() for i in range(500)]
|
n.connections.remove(n)
|
||||||
# for n in nodes:
|
self.assertRaises(RuntimeError, cPickle.dumps, n)
|
||||||
# n.connections = list(nodes)
|
|
||||||
# n.connections.remove(n)
|
|
||||||
# self.assertRaises(RuntimeError, cPickle.dumps, n)
|
|
||||||
|
|
||||||
def test_issue3179(self):
|
def test_issue3179(self):
|
||||||
'''Safe test, because of I broken this case when fixing the
|
# Safe test, because I broke this case when fixing the
|
||||||
behaviour for the previous test.
|
# behaviour for the previous test.
|
||||||
'''
|
|
||||||
res=[]
|
res=[]
|
||||||
for x in range(1,2000):
|
for x in range(1,2000):
|
||||||
res.append(dict(doc=x, similar=[]))
|
res.append(dict(doc=x, similar=[]))
|
||||||
|
|
|
@ -339,7 +339,6 @@ typedef struct Picklerobject {
|
||||||
int bin;
|
int bin;
|
||||||
|
|
||||||
int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
|
int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
|
||||||
int nesting;
|
|
||||||
int (*write_func)(struct Picklerobject *, const char *, Py_ssize_t);
|
int (*write_func)(struct Picklerobject *, const char *, Py_ssize_t);
|
||||||
char *write_buf;
|
char *write_buf;
|
||||||
int buf_size;
|
int buf_size;
|
||||||
|
@ -1630,7 +1629,12 @@ save_list(Picklerobject *self, PyObject *args)
|
||||||
iter = PyObject_GetIter(args);
|
iter = PyObject_GetIter(args);
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
||||||
|
if (Py_EnterRecursiveCall(" while pickling an object") == 0)
|
||||||
|
{
|
||||||
res = batch_list(self, iter);
|
res = batch_list(self, iter);
|
||||||
|
Py_LeaveRecursiveCall();
|
||||||
|
}
|
||||||
Py_DECREF(iter);
|
Py_DECREF(iter);
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -1786,7 +1790,11 @@ save_dict(Picklerobject *self, PyObject *args)
|
||||||
iter = PyObject_CallMethod(args, "iteritems", "()");
|
iter = PyObject_CallMethod(args, "iteritems", "()");
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
goto finally;
|
goto finally;
|
||||||
|
if (Py_EnterRecursiveCall(" while pickling an object") == 0)
|
||||||
|
{
|
||||||
res = batch_dict(self, iter);
|
res = batch_dict(self, iter);
|
||||||
|
Py_LeaveRecursiveCall();
|
||||||
|
}
|
||||||
Py_DECREF(iter);
|
Py_DECREF(iter);
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -2306,11 +2314,8 @@ save(Picklerobject *self, PyObject *args, int pers_save)
|
||||||
int res = -1;
|
int res = -1;
|
||||||
int tmp, size;
|
int tmp, size;
|
||||||
|
|
||||||
if (self->nesting++ > Py_GetRecursionLimit()){
|
if (Py_EnterRecursiveCall(" while pickling an object"))
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
return -1;
|
||||||
"maximum recursion depth exceeded");
|
|
||||||
goto finally;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pers_save && self->pers_func) {
|
if (!pers_save && self->pers_func) {
|
||||||
if ((tmp = save_pers(self, args, self->pers_func)) != 0) {
|
if ((tmp = save_pers(self, args, self->pers_func)) != 0) {
|
||||||
|
@ -2559,7 +2564,7 @@ save(Picklerobject *self, PyObject *args, int pers_save)
|
||||||
res = save_reduce(self, t, args);
|
res = save_reduce(self, t, args);
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self->nesting--;
|
Py_LeaveRecursiveCall();
|
||||||
Py_XDECREF(py_ob_id);
|
Py_XDECREF(py_ob_id);
|
||||||
Py_XDECREF(__reduce__);
|
Py_XDECREF(__reduce__);
|
||||||
Py_XDECREF(t);
|
Py_XDECREF(t);
|
||||||
|
@ -2801,7 +2806,6 @@ newPicklerobject(PyObject *file, int proto)
|
||||||
self->inst_pers_func = NULL;
|
self->inst_pers_func = NULL;
|
||||||
self->write_buf = NULL;
|
self->write_buf = NULL;
|
||||||
self->fast = 0;
|
self->fast = 0;
|
||||||
self->nesting = 0;
|
|
||||||
self->fast_container = 0;
|
self->fast_container = 0;
|
||||||
self->fast_memo = NULL;
|
self->fast_memo = NULL;
|
||||||
self->buf_size = 0;
|
self->buf_size = 0;
|
||||||
|
|
Loading…
Reference in New Issue