[Zodb-checkins] SVN: ZODB/branches/3.3/ Forward port from ZODB 3.2.
Tim Peters
tim.one at comcast.net
Tue Nov 16 16:51:58 EST 2004
Log message for revision 28466:
Forward port from ZODB 3.2.
Collector 1581: fspack can blow up when .fs is corrupted
Repaired three places where fspack referenced an undefined global while
*trying* to raise CorruptedError. Added new checkCorruptionInPack()
test to verify the correct exception gets raised.
Changed:
U ZODB/branches/3.3/NEWS.txt
U ZODB/branches/3.3/src/ZODB/FileStorage/fspack.py
U ZODB/branches/3.3/src/ZODB/tests/testFileStorage.py
-=-
Modified: ZODB/branches/3.3/NEWS.txt
===================================================================
--- ZODB/branches/3.3/NEWS.txt 2004-11-16 21:46:32 UTC (rev 28465)
+++ ZODB/branches/3.3/NEWS.txt 2004-11-16 21:51:58 UTC (rev 28466)
@@ -28,6 +28,15 @@
has been changed to obtain the class path from the object's pickle, without
trying to import application modules or classes.
+FileStorage
+-----------
+
+Collector 1581: When an attempt to pack a corrupted ``Data.fs`` file was
+made, it was possible for the pack routine to die with a reference to an
+undefined global while it was trying to raise ``CorruptedError``. It
+raises ``CorruptedError``, as it always intended, in these cases now.
+
+
Install
-------
Modified: ZODB/branches/3.3/src/ZODB/FileStorage/fspack.py
===================================================================
--- ZODB/branches/3.3/src/ZODB/FileStorage/fspack.py 2004-11-16 21:46:32 UTC (rev 28465)
+++ ZODB/branches/3.3/src/ZODB/FileStorage/fspack.py 2004-11-16 21:51:58 UTC (rev 28466)
@@ -264,7 +264,7 @@
if tlen != th.tlen:
self.fail(pos, "redundant transaction length does not "
"match initial transaction length: %d != %d",
- u64(s), th.tlen)
+ tlen, th.tlen)
pos += 8
self.packpos = pos
@@ -359,7 +359,7 @@
if tlen != th.tlen:
self.fail(pos, "redundant transaction length does not "
"match initial transaction length: %d != %d",
- u64(s), th.tlen)
+ tlen, th.tlen)
pos += 8
for pos in extra_roots:
@@ -553,7 +553,7 @@
if tlen != th.tlen:
self.fail(pos, "redundant transaction length does not "
"match initial transaction length: %d != %d",
- u64(s), th.tlen)
+ tlen, th.tlen)
pos += 8
return pos, new_pos
Modified: ZODB/branches/3.3/src/ZODB/tests/testFileStorage.py
===================================================================
--- ZODB/branches/3.3/src/ZODB/tests/testFileStorage.py 2004-11-16 21:46:32 UTC (rev 28465)
+++ ZODB/branches/3.3/src/ZODB/tests/testFileStorage.py 2004-11-16 21:51:58 UTC (rev 28466)
@@ -167,7 +167,56 @@
self.failUnless(self._storage._records_before_save > 20)
+ def checkCorruptionInPack(self):
+ # This sets up a corrupt .fs file, with a redundant transaction
+ # length mismatch. The implementation of pack in many releases of
+ # ZODB blew up if the .fs file had such damage: it detected the
+ # damage, but the code to raise CorruptedError referenced an undefined
+ # global.
+ import time
+ from ZODB.DB import DB
+ from ZODB.utils import U64, p64
+ from ZODB.FileStorage.format import CorruptedError
+
+ db = DB(self._storage)
+ conn = db.open()
+ conn.root()['xyz'] = 1
+ get_transaction().commit()
+
+ # Ensure it's all on disk.
+ db.close()
+ self._storage.close()
+
+ # Reopen before damaging.
+ self.open()
+
+ # Open .fs directly, and damage content.
+ f = open('FileStorageTests.fs', 'r+b')
+ f.seek(0, 2)
+ pos2 = f.tell() - 8
+ f.seek(pos2)
+ tlen2 = U64(f.read(8)) # length-8 of the last transaction
+ pos1 = pos2 - tlen2 + 8 # skip over the tid at the start
+ f.seek(pos1)
+ tlen1 = U64(f.read(8)) # should be redundant length-8
+ self.assertEqual(tlen1, tlen2) # verify that it is redundant
+
+ # Now damage the second copy.
+ f.seek(pos2)
+ f.write(p64(tlen2 - 1))
+ f.close()
+
+ # Try to pack. This used to yield
+ # NameError: global name 's' is not defined
+ try:
+ self._storage.pack(time.time(), None)
+ except CorruptedError, detail:
+ self.assert_("redundant transaction length does not match "
+ "initial transaction length" in str(detail))
+ else:
+ self.fail("expected CorruptedError")
+
class FileStorageRecoveryTest(
StorageTestBase.StorageTestBase,
RecoveryStorage.RecoveryStorage,
More information about the Zodb-checkins
mailing list