diff --git a/src/borg/repository.py b/src/borg/repository.py index 8665bba9c3..71ed4df169 100644 --- a/src/borg/repository.py +++ b/src/borg/repository.py @@ -1,5 +1,6 @@ import io import os +import re import sys import threading import time @@ -34,6 +35,9 @@ logger = create_logger(__name__) +# an object name is its sha256 as 64 lowercase hex digits. +_valid_object_name = re.compile(r"[0-9a-f]{64}").fullmatch + def repo_lister(repository, *, limit=None): marker = None @@ -1046,6 +1050,16 @@ def store_list(namespace): if index_errors == 0: # packs are the bulk of the work and the part --max-duration spreads over several checks. pack_infos = store_list("packs") + # drop objects whose name is not a valid pack name and count them as errors; the code + # below decodes each name via hex_to_bin, which only accepts valid names. + valid_pack_infos = [] + for info in pack_infos: + if _valid_object_name(info.name): + valid_pack_infos.append(info) + else: + logger.error(f"Store object packs/{info.name} has an invalid name.") + pack_errors += 1 + pack_infos = valid_pack_infos if partial: # a partial check stops after max_duration; verify the least-recently-checked packs # first so repeated runs cover every pack. sort by recorded check time, unrecorded diff --git a/src/borg/testsuite/repository_test.py b/src/borg/testsuite/repository_test.py index bd1f392ed7..34d39646fb 100644 --- a/src/borg/testsuite/repository_test.py +++ b/src/borg/testsuite/repository_test.py @@ -1056,6 +1056,21 @@ def test_check_detects_index_corruption(tmp_path): assert repository.check(repair=False) is False # mismatch between content hash and name detected +def test_check_reports_invalid_pack_name(tmp_path, caplog): + # an object in packs/ whose name is not 64 hex digits is reported as an error, and the other + # packs are still checked. + with Repository(str(tmp_path / "repo"), exclusive=True, create=True) as repository: + intact_id, _ = _store_intact_pack(repository) + repository.store_store("packs/not-a-hex-name", b"stray junk") + + with caplog.at_level(logging.ERROR, logger="borg.repository"): + assert repository.check(repair=False) is False + + assert "packs/not-a-hex-name has an invalid name" in caplog.text + after = PackTracker.load(repository.store) + assert after.table[intact_id].result == 1 # the valid pack was checked + + def test_check_warns_on_invalid_chunk_index(tmp_path, caplog): # check warns about an invalid chunk index but does not fail, since the index is not part of # the repository's object integrity.