Issue #10987: Fix the recursion limit handling in the _pickle module.
This commit is contained in:
parent
0929b1fc70
commit
e6d4c5bab8
|
@ -16,6 +16,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10987: Fix the recursion limit handling in the _pickle module.
|
||||||
|
|
||||||
- Issue #10983: Fix several bugs making tunnel requests in http.client.
|
- Issue #10983: Fix several bugs making tunnel requests in http.client.
|
||||||
|
|
||||||
- Issue #10955: zipimport uses ASCII encoding instead of cp437 to decode
|
- Issue #10955: zipimport uses ASCII encoding instead of cp437 to decode
|
||||||
|
|
|
@ -2244,19 +2244,21 @@ save_list(PicklerObject *self, PyObject *obj)
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
/* Materialize the list elements. */
|
/* Materialize the list elements. */
|
||||||
if (PyList_CheckExact(obj) && self->proto > 0) {
|
if (PyList_CheckExact(obj) && self->proto > 0) {
|
||||||
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
|
if (Py_EnterRecursiveCall(" while pickling an object"))
|
||||||
status = batch_list_exact(self, obj);
|
goto error;
|
||||||
Py_LeaveRecursiveCall();
|
status = batch_list_exact(self, obj);
|
||||||
}
|
Py_LeaveRecursiveCall();
|
||||||
} else {
|
} else {
|
||||||
PyObject *iter = PyObject_GetIter(obj);
|
PyObject *iter = PyObject_GetIter(obj);
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
|
if (Py_EnterRecursiveCall(" while pickling an object")) {
|
||||||
status = batch_list(self, iter);
|
Py_DECREF(iter);
|
||||||
Py_LeaveRecursiveCall();
|
goto error;
|
||||||
}
|
}
|
||||||
|
status = batch_list(self, iter);
|
||||||
|
Py_LeaveRecursiveCall();
|
||||||
Py_DECREF(iter);
|
Py_DECREF(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2504,10 +2506,10 @@ save_dict(PicklerObject *self, PyObject *obj)
|
||||||
if (PyDict_CheckExact(obj) && self->proto > 0) {
|
if (PyDict_CheckExact(obj) && self->proto > 0) {
|
||||||
/* We can take certain shortcuts if we know this is a dict and
|
/* We can take certain shortcuts if we know this is a dict and
|
||||||
not a dict subclass. */
|
not a dict subclass. */
|
||||||
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
|
if (Py_EnterRecursiveCall(" while pickling an object"))
|
||||||
status = batch_dict_exact(self, obj);
|
goto error;
|
||||||
Py_LeaveRecursiveCall();
|
status = batch_dict_exact(self, obj);
|
||||||
}
|
Py_LeaveRecursiveCall();
|
||||||
} else {
|
} else {
|
||||||
items = PyObject_CallMethod(obj, "items", "()");
|
items = PyObject_CallMethod(obj, "items", "()");
|
||||||
if (items == NULL)
|
if (items == NULL)
|
||||||
|
@ -2516,7 +2518,12 @@ save_dict(PicklerObject *self, PyObject *obj)
|
||||||
Py_DECREF(items);
|
Py_DECREF(items);
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
if (Py_EnterRecursiveCall(" while pickling an object")) {
|
||||||
|
Py_DECREF(iter);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
status = batch_dict(self, iter);
|
status = batch_dict(self, iter);
|
||||||
|
Py_LeaveRecursiveCall();
|
||||||
Py_DECREF(iter);
|
Py_DECREF(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3044,7 +3051,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
|
||||||
PyObject *reduce_value = NULL;
|
PyObject *reduce_value = NULL;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (Py_EnterRecursiveCall(" while pickling an object") < 0)
|
if (Py_EnterRecursiveCall(" while pickling an object"))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* The extra pers_save argument is necessary to avoid calling save_pers()
|
/* The extra pers_save argument is necessary to avoid calling save_pers()
|
||||||
|
|
|
@ -77,14 +77,15 @@ def test_cpickle(_cache={}):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("cannot import _pickle, skipped!")
|
print("cannot import _pickle, skipped!")
|
||||||
return
|
return
|
||||||
l = None
|
k, l = None, None
|
||||||
for n in itertools.count():
|
for n in itertools.count():
|
||||||
try:
|
try:
|
||||||
l = _cache[n]
|
l = _cache[n]
|
||||||
continue # Already tried and it works, let's save some time
|
continue # Already tried and it works, let's save some time
|
||||||
except KeyError:
|
except KeyError:
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
l = [l]
|
l = [k, l]
|
||||||
|
k = {i: l}
|
||||||
_pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
|
_pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
|
||||||
_cache[n] = l
|
_cache[n] = l
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue