From fa5c1d83268c45681b83af56541fd71e9e401d79 Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Fri, 2 Jan 2009 12:15:54 -0700
Subject: [PATCH] immutable: ReadBucketProxy defines classes of exception:
 LayoutInvalid and its two subtypes RidiculouslyLargeURIExtensionBlock and
 ShareVersionIncompatible.  This helps users (such as verifier/repairer) catch
 certain classes of reasons for "why did this download not work".  This code
 gets exercised by the verifier/repairer unit tests, which corrupt the shares
 on disk in order to trigger problems like these.

---
 src/allmydata/immutable/layout.py | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/allmydata/immutable/layout.py b/src/allmydata/immutable/layout.py
index cb9eb890..99f5bcbe 100644
--- a/src/allmydata/immutable/layout.py
+++ b/src/allmydata/immutable/layout.py
@@ -7,6 +7,21 @@ from allmydata.util import mathutil, idlib
 from allmydata.util.assertutil import _assert, precondition
 from allmydata import storage
 
+class LayoutInvalid(Exception):
+    """ There is something wrong with these bytes so they can't be interpreted as the kind of
+    immutable file that I know how to download. """
+    pass
+
+class RidiculouslyLargeURIExtensionBlock(LayoutInvalid):
+    """ When downloading a file, the length of the URI Extension Block was given as >= 2**32.
+    This means the share data must have been corrupted, or else the original uploader of the
+    file wrote a ridiculous value into the URI Extension Block length. """
+    pass
+
+class ShareVersionIncompatible(LayoutInvalid):
+    """ When downloading a share, its format was not one of the formats we know how to
+    parse. """
+    pass
 
 """
 Share data is written in a file. At the start of the file, there is a series of four-byte
@@ -272,7 +287,8 @@ class ReadBucketProxy:
         precondition(len(data) >= 0x4)
         self._offsets = {}
         (version,) = struct.unpack(">L", data[0:4])
-        _assert(version in (1,2))
+        if version != 1 and version != 2:
+            raise ShareVersionIncompatible(version)
 
         if version == 1:
             precondition(len(data) >= 0x24)
@@ -356,6 +372,12 @@ class ReadBucketProxy:
         d = self._read(offset, self._fieldsize)
         def _got_length(data):
             length = struct.unpack(self._fieldstruct, data)[0]
+            if length >= 2**31:
+                # URI extension blocks are around 419 bytes long, so this must be corrupted.
+                # Anyway, the foolscap interface schema for "read" will not allow >= 2**31 bytes
+                # length.
+                raise RidiculouslyLargeURIExtensionBlock(length)
+
             return self._read(offset+self._fieldsize, length)
         d.addCallback(_got_length)
         return d
-- 
2.45.2