]> granicus.if.org Git - python/commitdiff
Issue 5794: fix cPickle's unpickling of recursive tuples.
authorCollin Winter <collinw@gmail.com>
Tue, 26 May 2009 04:12:39 +0000 (04:12 +0000)
committerCollin Winter <collinw@gmail.com>
Tue, 26 May 2009 04:12:39 +0000 (04:12 +0000)
Lib/test/pickletester.py
Lib/test/test_cpickle.py
Modules/cPickle.c

index bc0be1f845c50a3c00d18d8f09ed0dde3adfbb9e..ce49fdda78e97e821371fcc568c344002897d9a7 100644 (file)
@@ -463,6 +463,16 @@ class AbstractPickleTests(unittest.TestCase):
             self.assertEqual(len(x), 1)
             self.assert_(x is x[0])
 
+    def test_recursive_tuple(self):
+        t = ([],)
+        t[0].append(t)
+        for proto in protocols:
+            s = self.dumps(t, proto)
+            x = self.loads(s)
+            self.assertEqual(len(x), 1)
+            self.assertEqual(len(x[0]), 1)
+            self.assert_(x is x[0][0])
+
     def test_recursive_dict(self):
         d = {}
         d[1] = d
index 054187313f8ba18fad8bb0ae1c263903a1565574..c240669873a1a5734a00fcd78cf1151d249df0e2 100644 (file)
@@ -65,6 +65,11 @@ class cPickleFastPicklerTests(AbstractPickleTests):
                           AbstractPickleTests.test_recursive_list,
                           self)
 
+    def test_recursive_tuple(self):
+        self.assertRaises(ValueError,
+                          AbstractPickleTests.test_recursive_tuple,
+                          self)
+
     def test_recursive_inst(self):
         self.assertRaises(ValueError,
                           AbstractPickleTests.test_recursive_inst,
index fbb1888aaa9f3c6dc689fde29d4c8602a9a43895..486e86fc125484227b9d24fa9e8895424c1d3591 100644 (file)
@@ -4086,25 +4086,24 @@ load_binpersid(Unpicklerobject *self)
 static int
 load_pop(Unpicklerobject *self)
 {
-       int len;
-
-       if (!( (len=self->stack->length) > 0 ))  return stackUnderflow();
+       int len = self->stack->length;
 
        /* Note that we split the (pickle.py) stack into two stacks,
           an object stack and a mark stack. We have to be clever and
           pop the right one. We do this by looking at the top of the
-          mark stack.
+          mark stack first, and only signalling a stack underflow if
+          the object stack is empty and the mark stack doesn't match
+          our expectations.
        */
-
-       if ((self->num_marks > 0) &&
-           (self->marks[self->num_marks - 1] == len))
+       if (self->num_marks > 0 && self->marks[self->num_marks - 1] == len) {
                self->num_marks--;
-       else {
+       } else if (len >= 0) {
                len--;
                Py_DECREF(self->stack->data[len]);
-               self->stack->length=len;
+               self->stack->length = len;
+       } else {
+               return stackUnderflow();
        }
-
        return 0;
 }