2
0
Эх сурвалжийг харах

better validation of item metadata dicts, fixes #1130

the previous check only checked that we got a dict, but did not validate the dict keys.
this triggered issues with e.g. (invalid) integer keys.

now it validates the keys:
- some required keys must be present
- the set of keys is a subset of all valid keys
Thomas Waldmann 9 жил өмнө
parent
commit
a7b5165149
1 өөрчлөгдсөн 12 нэмэгдсэн , 3 устгасан
  1. 12 3
      borg/archive.py

+ 12 - 3
borg/archive.py

@@ -591,6 +591,9 @@ ITEM_KEYS = frozenset([b'path', b'source', b'rdev', b'chunks',
                        b'mode', b'user', b'group', b'uid', b'gid', b'mtime', b'atime', b'ctime',
                        b'mode', b'user', b'group', b'uid', b'gid', b'mtime', b'atime', b'ctime',
                        b'xattrs', b'bsdflags', b'acl_nfs4', b'acl_access', b'acl_default', b'acl_extended', ])
                        b'xattrs', b'bsdflags', b'acl_nfs4', b'acl_access', b'acl_default', b'acl_extended', ])
 
 
+# this is the set of keys that are always present in items:
+REQUIRED_ITEM_KEYS = frozenset([b'path', b'mtime', ])
+
 
 
 def valid_msgpacked_item(d, item_keys_serialized):
 def valid_msgpacked_item(d, item_keys_serialized):
     """check if the data <d> looks like a msgpacked item metadata dict"""
     """check if the data <d> looks like a msgpacked item metadata dict"""
@@ -811,8 +814,8 @@ class ArchiveChecker:
 
 
             Missing item chunks will be skipped and the msgpack stream will be restarted
             Missing item chunks will be skipped and the msgpack stream will be restarted
             """
             """
-            unpacker = RobustUnpacker(lambda item: isinstance(item, dict) and b'path' in item,
-                                      self.manifest.item_keys)
+            item_keys = self.manifest.item_keys
+            unpacker = RobustUnpacker(lambda item: isinstance(item, dict) and b'path' in item, item_keys)
             _state = 0
             _state = 0
 
 
             def missing_chunk_detector(chunk_id):
             def missing_chunk_detector(chunk_id):
@@ -827,6 +830,12 @@ class ArchiveChecker:
                 self.error_found = True
                 self.error_found = True
                 logger.error(msg)
                 logger.error(msg)
 
 
+            def valid_item(obj):
+                if not isinstance(obj, StableDict):
+                    return False
+                keys = set(obj)
+                return REQUIRED_ITEM_KEYS.issubset(keys) and keys.issubset(item_keys)
+
             i = 0
             i = 0
             for state, items in groupby(archive[b'items'], missing_chunk_detector):
             for state, items in groupby(archive[b'items'], missing_chunk_detector):
                 items = list(items)
                 items = list(items)
@@ -841,7 +850,7 @@ class ArchiveChecker:
                     unpacker.feed(self.key.decrypt(chunk_id, cdata))
                     unpacker.feed(self.key.decrypt(chunk_id, cdata))
                     try:
                     try:
                         for item in unpacker:
                         for item in unpacker:
-                            if isinstance(item, dict):
+                            if valid_item(item):
                                 yield item
                                 yield item
                             else:
                             else:
                                 report('Did not get expected metadata dict when unpacking item metadata', chunk_id, i)
                                 report('Did not get expected metadata dict when unpacking item metadata', chunk_id, i)