Преглед изворни кода

Raise EmptyFileException when empty disk file corruption is detected

Related #582
Antoine R. Dumont (@ardumont) пре 7 година
родитељ
комит
d74761abde
5 измењених фајлова са 44 додато и 0 уклоњено
  1. 3 0
      NEWS
  2. 7 0
      dulwich/errors.py
  3. 2 0
      dulwich/object_store.py
  4. 4 0
      dulwich/objects.py
  5. 28 0
      dulwich/tests/test_object_store.py

+ 3 - 0
NEWS

@@ -17,6 +17,9 @@
 
   * Fix error message for missing trailing ]. (Daniel Andersson)
 
+  * Raise EmptyFileException when corruption (in the form of an empty
+    file) is detected. (Antoine R. Dumont, #582)
+
   IMPROVEMENTS
 
   * Enforce date field parsing consistency. This also add checks on

+ 7 - 0
dulwich/errors.py

@@ -164,6 +164,13 @@ class ObjectFormatException(FileFormatException):
     """Indicates an error parsing an object."""
 
 
+class EmptyFileException(FileFormatException):
+    """Indicates an empty file instead of the object's disk
+       representation.
+
+    """
+
+
 class NoIndexPresent(Exception):
     """No index is present."""
 

+ 2 - 0
dulwich/object_store.py

@@ -25,6 +25,7 @@
 from io import BytesIO
 import errno
 from itertools import chain
+import logging
 import os
 import stat
 import sys
@@ -456,6 +457,7 @@ class DiskObjectStore(PackBasedObjectStore):
         self._pack_cache_time = 0
         self._pack_cache = {}
         self._alternates = None
+        self.log = logging.getLogger('dulwich.object_store.DiskObjectStore')
 
     def __repr__(self):
         return "<%s(%r)>" % (self.__class__.__name__, self.path)

+ 4 - 0
dulwich/objects.py

@@ -38,6 +38,7 @@ from dulwich.errors import (
     NotTagError,
     NotTreeError,
     ObjectFormatException,
+    EmptyFileException,
     )
 from dulwich.file import GitFile
 
@@ -362,6 +363,9 @@ class ShaFile(object):
     @classmethod
     def _parse_file(cls, f):
         map = f.read()
+        if not map:
+            raise EmptyFileException('Corrupted empty file detected')
+
         if cls._is_legacy_object(map):
             obj = cls._parse_legacy_object_header(map, f)
             obj._parse_legacy_object(map)

+ 28 - 0
dulwich/tests/test_object_store.py

@@ -33,6 +33,7 @@ from dulwich.index import (
     )
 from dulwich.errors import (
     NotTreeError,
+    EmptyFileException,
     )
 from dulwich.objects import (
     sha_to_hex,
@@ -343,6 +344,33 @@ class DiskObjectStoreTests(PackBasedObjectStoreTests, TestCase):
         self.assertIn(b2.id, store)
         self.assertEqual(b2, store[b2.id])
 
+    def test_corrupted_object_raise_exception(self):
+        """Corrupted sha1 disk file should raise specific exception"""
+        self.store.add_object(testobject)
+        self.assertEqual((Blob.type_num, b'yummy data'),
+                         self.store.get_raw(testobject.id))
+        self.assertTrue(self.store.contains_loose(testobject.id))
+        self.assertIsNotNone(self.store._get_loose_object(testobject.id))
+
+        path = self.store._get_shafile_path(testobject.id)
+        with open(path, 'wb') as f:  # corrupt the file
+            f.write(b'')
+
+        expected_error_msg = 'Corrupted empty file detected'
+        try:
+            self.store.contains_loose(testobject.id)
+        except EmptyFileException as e:
+            self.assertEqual(str(e), expected_error_msg)
+
+        try:
+            self.store._get_loose_object(testobject.id)
+        except EmptyFileException as e:
+            self.assertEqual(str(e), expected_error_msg)
+
+        # this does not change iteration on loose objects though
+        self.assertEqual([testobject.id],
+                         list(self.store._iter_loose_objects()))
+
     def test_add_alternate_path(self):
         store = DiskObjectStore(self.store_dir)
         self.assertEqual([], list(store._read_alternate_paths()))