Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/borg/repository.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import io
import os
import re
import sys
import threading
import time
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions src/borg/testsuite/repository_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading