From e9a651476760fea6dfa12b9621ce57f015823b69 Mon Sep 17 00:00:00 2001 From: Collin Winter Date: Tue, 26 May 2009 05:37:22 +0000 Subject: [PATCH] Merged revisions 72930 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72930 | collin.winter | 2009-05-25 21:12:39 -0700 (Mon, 25 May 2009) | 1 line Issue 5794: fix cPickle's unpickling of recursive tuples. ........ --- Lib/test/pickletester.py | 10 ++++++++++ Lib/test/test_cpickle.py | 5 +++++ Modules/cPickle.c | 19 +++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index e34d55b85d1..f7099a1b300 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -428,6 +428,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 diff --git a/Lib/test/test_cpickle.py b/Lib/test/test_cpickle.py index 0b02b624734..c874481cdd6 100644 --- a/Lib/test/test_cpickle.py +++ b/Lib/test/test_cpickle.py @@ -64,6 +64,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, diff --git a/Modules/cPickle.c b/Modules/cPickle.c index fb13ba18bc4..1cef5c1f704 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -4016,25 +4016,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; }