From ee4df920b8ce6805843fb564eaa719468549a9b1 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Fri, 7 Jun 2013 16:47:43 -0400 Subject: [PATCH] Strip protocol header from pickles where protocol > 1. --- src/ZODB/tests/testUtils.py | 47 ++++++++++++++++++++++++++++++------- src/ZODB/utils.py | 3 +++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/ZODB/tests/testUtils.py b/src/ZODB/tests/testUtils.py index 87a52a2b0..06574c586 100644 --- a/src/ZODB/tests/testUtils.py +++ b/src/ZODB/tests/testUtils.py @@ -41,7 +41,7 @@ class TestUtils(unittest.TestCase): for i in range(NUM)] all = small + large - def checkLongToStringToLong(self): + def test_LongToStringToLong(self): for num in self.all: s = p64(num) n = U64(s) @@ -49,7 +49,7 @@ def checkLongToStringToLong(self): n2 = u64(s) self.assertEqual(num, n2, "u64() failed") - def checkKnownConstants(self): + def test_KnownConstants(self): self.assertEqual(b"\000\000\000\000\000\000\000\001", p64(1)) self.assertEqual(b"\000\000\000\001\000\000\000\000", p64(1<<32)) self.assertEqual(u64(b"\000\000\000\000\000\000\000\001"), 1) @@ -57,7 +57,7 @@ def checkKnownConstants(self): self.assertEqual(u64(b"\000\000\000\001\000\000\000\000"), 1<<32) self.assertEqual(U64(b"\000\000\000\001\000\000\000\000"), 1<<32) - def checkPersistentIdHandlesDescriptor(self): + def test_PersistentIdHandlesDescriptor(self): from ZODB.serialize import ObjectWriter class P(Persistent): pass @@ -70,7 +70,7 @@ class P(Persistent): # deduce the class path from a pickle, instead of actually loading # the pickle (and so also trying to import application module and # class objects, which isn't a good idea on a ZEO server when avoidable). - def checkConflictErrorDoesntImport(self): + def test_ConflictErrorDoesntImport(self): from ZODB.serialize import ObjectWriter from ZODB.POSException import ConflictError from ZODB.tests.MinPO import MinPO @@ -98,9 +98,40 @@ def checkConflictErrorDoesntImport(self): else: self.fail("expected ConflictError, but no exception raised") + def test_get_pickle_metadata_w_protocol_0_class_pickle(self): + from ZODB.utils import get_pickle_metadata + from ZODB._compat import dumps + pickle = dumps(ExampleClass, protocol=0) + self.assertEqual(get_pickle_metadata(pickle), + (__name__, ExampleClass.__name__)) + + def test_get_pickle_metadata_w_protocol_1_class_pickle(self): + from ZODB.utils import get_pickle_metadata + from ZODB._compat import dumps + pickle = dumps(ExampleClass, protocol=1) + self.assertEqual(get_pickle_metadata(pickle), + (__name__, ExampleClass.__name__)) + + def test_get_pickle_metadata_w_protocol_2_class_pickle(self): + from ZODB.utils import get_pickle_metadata + from ZODB._compat import dumps + pickle = dumps(ExampleClass, protocol=2) + self.assertEqual(get_pickle_metadata(pickle), + (__name__, ExampleClass.__name__)) + + def test_get_pickle_metadata_w_protocol_3_class_pickle(self): + from ZODB.utils import get_pickle_metadata + from ZODB._compat import dumps + pickle = dumps(ExampleClass, protocol=3) + self.assertEqual(get_pickle_metadata(pickle), + (__name__, ExampleClass.__name__)) + + +class ExampleClass(object): + pass def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestUtils, 'check')) - suite.addTest(doctest.DocFileSuite('../utils.txt', checker=checker)) - return suite + return unittest.TestSuite(( + unittest.makeSuite(TestUtils), + doctest.DocFileSuite('../utils.txt', checker=checker), + )) diff --git a/src/ZODB/utils.py b/src/ZODB/utils.py index 9219ab888..b8c1519ec 100644 --- a/src/ZODB/utils.py +++ b/src/ZODB/utils.py @@ -217,6 +217,9 @@ def get_pickle_metadata(data): # ZODB's data records contain two pickles. The first is the class # of the object, the second is the object. We're only trying to # pick apart the first here, to extract the module and class names. + if data[0] == 0x80: # protocol marker, protocol > 1 + protocol = data[1] + data = data[2:] if data.startswith(b'(c'): # pickle MARK GLOBAL opcode sequence global_prefix = 2 elif data.startswith(b'c'): # pickle GLOBAL opcode