diff options
author | Tim Peters <tim.peters@gmail.com> | 2003-02-02 20:29:39 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2003-02-02 20:29:39 (GMT) |
commit | 1d63c9f15134a2776b39fb979c506637f73c8a51 (patch) | |
tree | 3e982922147a9e1ce2c8ae974f0ef61d6956397f /Lib | |
parent | 9af6968b9066f1be419d09d68af0d0659a7ba991 (diff) | |
download | cpython-1d63c9f15134a2776b39fb979c506637f73c8a51.zip cpython-1d63c9f15134a2776b39fb979c506637f73c8a51.tar.gz cpython-1d63c9f15134a2776b39fb979c506637f73c8a51.tar.bz2 |
cPickle support for TUPLE[123]. Incidentally plugged several undetected
overflow holes in Pdata_grow().
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/pickle.py | 16 | ||||
-rw-r--r-- | Lib/test/pickletester.py | 31 |
2 files changed, 40 insertions, 7 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index 4e80cca..926869e 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -621,8 +621,11 @@ class Pickler: proto = self.proto n = len(obj) - if n == 0 and proto: - write(EMPTY_TUPLE) + if n == 0: + if proto: + write(EMPTY_TUPLE) + else: + write(MARK + TUPLE) return save = self.save @@ -639,13 +642,13 @@ class Pickler: self.memoize(obj) return - # proto 0, or proto 1 and tuple isn't empty, or proto > 1 and tuple + # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple # has more than 3 elements. write(MARK) for element in obj: save(element) - if n and id(obj) in memo: + if id(obj) in memo: # Subtle. d was not in memo when we entered save_tuple(), so # the process of saving the tuple's elements must have saved # the tuple itself: the tuple is recursive. The proper action @@ -660,10 +663,9 @@ class Pickler: write(POP * (n+1) + get) return - # No recursion (including the empty-tuple case for protocol 0). + # No recursion. self.write(TUPLE) - if obj: # No need to memoize empty tuple - self.memoize(obj) + self.memoize(obj) dispatch[TupleType] = save_tuple diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index f1a1384..249cc54 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -484,6 +484,27 @@ class AbstractPickleTests(unittest.TestCase): self.assertEqual(x, y) def test_short_tuples(self): + # Map (proto, len(tuple)) to expected opcode. + expected_opcode = {(0, 0): pickle.TUPLE, + (0, 1): pickle.TUPLE, + (0, 2): pickle.TUPLE, + (0, 3): pickle.TUPLE, + (0, 4): pickle.TUPLE, + + (1, 0): pickle.EMPTY_TUPLE, + (1, 1): pickle.TUPLE, + (1, 2): pickle.TUPLE, + (1, 3): pickle.TUPLE, + (1, 4): pickle.TUPLE, + + (2, 0): pickle.EMPTY_TUPLE, + (2, 1): pickle.TUPLE1, + (2, 2): pickle.TUPLE2, + (2, 3): pickle.TUPLE3, + (2, 4): pickle.TUPLE, + } + all_tuple_opcodes = (pickle.TUPLE, pickle.EMPTY_TUPLE, + pickle.TUPLE1, pickle.TUPLE2, pickle.TUPLE3) a = () b = (1,) c = (1, 2) @@ -495,6 +516,16 @@ class AbstractPickleTests(unittest.TestCase): y = self.loads(s) self.assertEqual(x, y, (proto, x, s, y)) + # Verify that the protocol-correct tuple-building opcode + # was generated. + expected = expected_opcode[proto, len(x)] + for opcode in s: + if opcode in all_tuple_opcodes: + self.assertEqual(expected, opcode) + break + else: + self.fail("didn't find a tuple-building opcode in pickle") + def test_singletons(self): for proto in protocols: for x in None, False, True: |