From a7b516514949db068fbc8747a8cec076c3a70f69 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 12 Jun 2016 00:10:39 +0200 Subject: [PATCH] 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 --- borg/archive.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/borg/archive.py b/borg/archive.py index 8638bc22a..370134671 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -591,6 +591,9 @@ def _open_rb(path): 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', ]) +# 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): """check if the data looks like a msgpacked item metadata dict""" @@ -811,8 +814,8 @@ def robust_iterator(archive): 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 def missing_chunk_detector(chunk_id): @@ -827,6 +830,12 @@ def report(msg, chunk_id, chunk_no): self.error_found = True 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 for state, items in groupby(archive[b'items'], missing_chunk_detector): items = list(items) @@ -841,7 +850,7 @@ def report(msg, chunk_id, chunk_no): unpacker.feed(self.key.decrypt(chunk_id, cdata)) try: for item in unpacker: - if isinstance(item, dict): + if valid_item(item): yield item else: report('Did not get expected metadata dict when unpacking item metadata', chunk_id, i)