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

Skip to content

Commit e6d4c5b

Browse files
committed
Issue #10987: Fix the recursion limit handling in the _pickle module.
1 parent 0929b1f commit e6d4c5b

3 files changed

Lines changed: 24 additions & 14 deletions

File tree

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Core and Builtins
1616
Library
1717
-------
1818

19+
- Issue #10987: Fix the recursion limit handling in the _pickle module.
20+
1921
- Issue #10983: Fix several bugs making tunnel requests in http.client.
2022

2123
- Issue #10955: zipimport uses ASCII encoding instead of cp437 to decode

Modules/_pickle.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,19 +2244,21 @@ save_list(PicklerObject *self, PyObject *obj)
22442244
if (len != 0) {
22452245
/* Materialize the list elements. */
22462246
if (PyList_CheckExact(obj) && self->proto > 0) {
2247-
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
2248-
status = batch_list_exact(self, obj);
2249-
Py_LeaveRecursiveCall();
2250-
}
2247+
if (Py_EnterRecursiveCall(" while pickling an object"))
2248+
goto error;
2249+
status = batch_list_exact(self, obj);
2250+
Py_LeaveRecursiveCall();
22512251
} else {
22522252
PyObject *iter = PyObject_GetIter(obj);
22532253
if (iter == NULL)
22542254
goto error;
22552255

2256-
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
2257-
status = batch_list(self, iter);
2258-
Py_LeaveRecursiveCall();
2256+
if (Py_EnterRecursiveCall(" while pickling an object")) {
2257+
Py_DECREF(iter);
2258+
goto error;
22592259
}
2260+
status = batch_list(self, iter);
2261+
Py_LeaveRecursiveCall();
22602262
Py_DECREF(iter);
22612263
}
22622264
}
@@ -2504,10 +2506,10 @@ save_dict(PicklerObject *self, PyObject *obj)
25042506
if (PyDict_CheckExact(obj) && self->proto > 0) {
25052507
/* We can take certain shortcuts if we know this is a dict and
25062508
not a dict subclass. */
2507-
if (Py_EnterRecursiveCall(" while pickling an object") == 0) {
2508-
status = batch_dict_exact(self, obj);
2509-
Py_LeaveRecursiveCall();
2510-
}
2509+
if (Py_EnterRecursiveCall(" while pickling an object"))
2510+
goto error;
2511+
status = batch_dict_exact(self, obj);
2512+
Py_LeaveRecursiveCall();
25112513
} else {
25122514
items = PyObject_CallMethod(obj, "items", "()");
25132515
if (items == NULL)
@@ -2516,7 +2518,12 @@ save_dict(PicklerObject *self, PyObject *obj)
25162518
Py_DECREF(items);
25172519
if (iter == NULL)
25182520
goto error;
2521+
if (Py_EnterRecursiveCall(" while pickling an object")) {
2522+
Py_DECREF(iter);
2523+
goto error;
2524+
}
25192525
status = batch_dict(self, iter);
2526+
Py_LeaveRecursiveCall();
25202527
Py_DECREF(iter);
25212528
}
25222529
}
@@ -3044,7 +3051,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
30443051
PyObject *reduce_value = NULL;
30453052
int status = 0;
30463053

3047-
if (Py_EnterRecursiveCall(" while pickling an object") < 0)
3054+
if (Py_EnterRecursiveCall(" while pickling an object"))
30483055
return -1;
30493056

30503057
/* The extra pers_save argument is necessary to avoid calling save_pers()

Tools/scripts/find_recursionlimit.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ def test_cpickle(_cache={}):
7777
except ImportError:
7878
print("cannot import _pickle, skipped!")
7979
return
80-
l = None
80+
k, l = None, None
8181
for n in itertools.count():
8282
try:
8383
l = _cache[n]
8484
continue # Already tried and it works, let's save some time
8585
except KeyError:
8686
for i in range(100):
87-
l = [l]
87+
l = [k, l]
88+
k = {i: l}
8889
_pickle.Pickler(io.BytesIO(), protocol=-1).dump(l)
8990
_cache[n] = l
9091

0 commit comments

Comments
 (0)