]> granicus.if.org Git - python/commitdiff
Issue #10987: Fix the recursion limit handling in the _pickle module.
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 23 Jan 2011 17:12:25 +0000 (17:12 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 23 Jan 2011 17:12:25 +0000 (17:12 +0000)
Misc/NEWS
Modules/_pickle.c
Tools/scripts/find_recursionlimit.py

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