]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
Sun Jan 8 22:12:47 GMT 2012 Brian Warner <warner@lothar.com>
authorDaira Hopwood <daira@jacaranda.org>
Thu, 5 Sep 2013 18:03:02 +0000 (19:03 +0100)
committerDaira Hopwood <daira@jacaranda.org>
Thu, 5 Sep 2013 18:03:02 +0000 (19:03 +0100)
  * mutable/layout.py: raise BadShareError instead of assert()

src/allmydata/mutable/common.py
src/allmydata/mutable/layout.py

index c8960c0ef3201e1183894f6d33b8569a92441f4b..9ce8e37c63af731663115e33e97f657853b8e16c 100644 (file)
@@ -11,7 +11,13 @@ MODE_REPAIR = "MODE_REPAIR" # query all peers, get the privkey
 class NotWriteableError(Exception):
     pass
 
-class NeedMoreDataError(Exception):
+class BadShareError(Exception):
+    """This represents an error discovered in a particular share, during
+    retrieve, from which we can recover by using some other share. This does
+    *not* include local coding errors.
+    """
+
+class NeedMoreDataError(BadShareError):
     def __init__(self, needed_bytes, encprivkey_offset, encprivkey_length):
         Exception.__init__(self)
         self.needed_bytes = needed_bytes # up through EOF
@@ -41,7 +47,7 @@ class NotEnoughServersError(Exception):
         Exception.__init__(self, why, first_error)
         self.first_error = first_error
 
-class CorruptShareError(Exception):
+class CorruptShareError(BadShareError):
     def __init__(self, server, shnum, reason):
         self.args = (server, shnum, reason)
         self.server = server
@@ -51,7 +57,7 @@ class CorruptShareError(Exception):
         return "<CorruptShareError server=%s shnum[%d]: %s" % \
                (self.server.get_name(), self.shnum, self.reason)
 
-class UnknownVersionError(Exception):
+class UnknownVersionError(BadShareError):
     """The share we received was of a version we don't recognize."""
 
 class ResponseCache:
index f83e9112440126dff35e51bb457fbe6ffed22c18..33d647b9cca0019bb27e8b4cb11b937a33a5fa72 100644 (file)
@@ -1,6 +1,7 @@
 
 import struct
-from allmydata.mutable.common import NeedMoreDataError, UnknownVersionError
+from allmydata.mutable.common import NeedMoreDataError, UnknownVersionError, \
+     BadShareError
 from allmydata.interfaces import HASH_SIZE, SALT_SIZE, SDMF_VERSION, \
                                  MDMF_VERSION, IMutableSlotWriter
 from allmydata.util import mathutil
@@ -116,7 +117,9 @@ def unpack_share(data):
     share_hash_chain_s = data[o['share_hash_chain']:o['block_hash_tree']]
     share_hash_format = ">H32s"
     hsize = struct.calcsize(share_hash_format)
-    assert len(share_hash_chain_s) % hsize == 0, len(share_hash_chain_s)
+    if len(share_hash_chain_s) % hsize != 0:
+        raise BadShareError("hash chain is %d bytes, not multiple of %d"
+                            % (len(share_hash_chain_s), hsize))
     share_hash_chain = []
     for i in range(0, len(share_hash_chain_s), hsize):
         chunk = share_hash_chain_s[i:i+hsize]
@@ -124,7 +127,9 @@ def unpack_share(data):
         share_hash_chain.append( (hid, h) )
     share_hash_chain = dict(share_hash_chain)
     block_hash_tree_s = data[o['block_hash_tree']:o['share_data']]
-    assert len(block_hash_tree_s) % 32 == 0, len(block_hash_tree_s)
+    if len(block_hash_tree_s) % 32 != 0:
+        raise BadShareError("block_hash_tree is %d bytes, not multiple of %d"
+                            % (len(block_hash_tree_s), 32))
     block_hash_tree = []
     for i in range(0, len(block_hash_tree_s), 32):
         block_hash_tree.append(block_hash_tree_s[i:i+32])
@@ -1169,6 +1174,11 @@ class MDMFSlotWriteProxy:
         d.addCallback(_result)
         return d
 
+def _handle_bad_struct(f):
+    # struct.unpack errors mean the server didn't give us enough data, so
+    # this share is bad
+    f.trap(struct.error)
+    raise BadShareError(f.value.args[0])
 
 class MDMFSlotReadProxy:
     """
@@ -1239,11 +1249,13 @@ class MDMFSlotReadProxy:
         d = self._read(readvs, force_remote)
         d.addCallback(self._process_encoding_parameters)
         d.addCallback(self._process_offsets)
+        d.addErrback(_handle_bad_struct)
         return d
 
 
     def _process_encoding_parameters(self, encoding_parameters):
-        assert self.shnum in encoding_parameters
+        if self.shnum not in encoding_parameters:
+            raise BadShareError("no data for shnum %d" % self.shnum)
         encoding_parameters = encoding_parameters[self.shnum][0]
         # The first byte is the version number. It will tell us what
         # to do next.
@@ -1388,7 +1400,8 @@ class MDMFSlotReadProxy:
         d.addCallback(_then)
         d.addCallback(lambda readvs: self._read(readvs))
         def _process_results(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
             if self._version_number == 0:
                 # We only read the share data, but we know the salt from
                 # when we fetched the header
@@ -1396,7 +1409,8 @@ class MDMFSlotReadProxy:
                 if not data:
                     data = ""
                 else:
-                    assert len(data) == 1
+                    if len(data) != 1:
+                        raise BadShareError("got %d vectors, not 1" % len(data))
                     data = data[0]
                 salt = self._salt
             else:
@@ -1446,7 +1460,8 @@ class MDMFSlotReadProxy:
         d.addCallback(lambda readvs:
             self._read(readvs, force_remote=force_remote))
         def _build_block_hash_tree(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
 
             rawhashes = results[self.shnum][0]
             results = [rawhashes[i:i+HASH_SIZE]
@@ -1485,7 +1500,8 @@ class MDMFSlotReadProxy:
         d.addCallback(lambda readvs:
             self._read(readvs, force_remote=force_remote))
         def _build_share_hash_chain(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
 
             sharehashes = results[self.shnum][0]
             results = [sharehashes[i:i+(HASH_SIZE + 2)]
@@ -1494,6 +1510,7 @@ class MDMFSlotReadProxy:
                             for data in results])
             return results
         d.addCallback(_build_share_hash_chain)
+        d.addErrback(_handle_bad_struct)
         return d
 
 
@@ -1514,7 +1531,8 @@ class MDMFSlotReadProxy:
         d.addCallback(_make_readvs)
         d.addCallback(lambda readvs: self._read(readvs))
         def _process_results(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
             privkey = results[self.shnum][0]
             return privkey
         d.addCallback(_process_results)
@@ -1538,7 +1556,8 @@ class MDMFSlotReadProxy:
         d.addCallback(_make_readvs)
         d.addCallback(lambda readvs: self._read(readvs))
         def _process_results(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
             signature = results[self.shnum][0]
             return signature
         d.addCallback(_process_results)
@@ -1563,7 +1582,8 @@ class MDMFSlotReadProxy:
         d.addCallback(_make_readvs)
         d.addCallback(lambda readvs: self._read(readvs))
         def _process_results(results):
-            assert self.shnum in results
+            if self.shnum not in results:
+                raise BadShareError("no data for shnum %d" % self.shnum)
             verification_key = results[self.shnum][0]
             return verification_key
         d.addCallback(_process_results)
@@ -1739,7 +1759,7 @@ class MDMFSlotReadProxy:
         return d
 
 
-class LayoutInvalid(Exception):
+class LayoutInvalid(BadShareError):
     """
     This isn't a valid MDMF mutable file
     """