From 2e6af653f6fa05c0706412fa6ac518a94081eb20 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Wed, 18 Feb 2026 22:40:22 +0100 Subject: [PATCH] hashindex: fixed iteritems segfaulting with non-existent marker, fixes #9368 Never happened in borg, because borg always gives existing markers to iteritems. Also: added test for this. --- src/borg/hashindex.pyx | 8 +++---- src/borg/testsuite/hashindex_pytest.py | 30 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/borg/testsuite/hashindex_pytest.py diff --git a/src/borg/hashindex.pyx b/src/borg/hashindex.pyx index 916df65ed..44f1fcbe1 100644 --- a/src/borg/hashindex.pyx +++ b/src/borg/hashindex.pyx @@ -237,8 +237,8 @@ cdef class NSIndex(IndexBase): iter.index = self.index if marker: key = hashindex_get(self.index, marker) - if marker is None: - raise IndexError + if not key: + raise KeyError("marker not found") iter.key = key - self.key_size return iter @@ -354,8 +354,8 @@ cdef class ChunkIndex(IndexBase): iter.index = self.index if marker: key = hashindex_get(self.index, marker) - if marker is None: - raise IndexError + if not key: + raise KeyError("marker not found") iter.key = key - self.key_size return iter diff --git a/src/borg/testsuite/hashindex_pytest.py b/src/borg/testsuite/hashindex_pytest.py new file mode 100644 index 000000000..4a82775c7 --- /dev/null +++ b/src/borg/testsuite/hashindex_pytest.py @@ -0,0 +1,30 @@ +import pytest +from borg.hashindex import NSIndex, ChunkIndex + +def test_nsindex_iteritems_marker(): + nsindex = NSIndex() + nsindex[b'\xbb'*32] = (123, 456) + nsindex[b'\xaa'*32] = (234, 567) + + # marker exists + items = list(nsindex.iteritems(marker=b'\xbb'*32)) + assert len(items) == 1 + assert items[0][0] == b'\xaa'*32 + + # marker does not exist + with pytest.raises(KeyError, match="marker not found"): + list(nsindex.iteritems(marker=b'\xcc'*32)) + +def test_chunkindex_iteritems_marker(): + chunkindex = ChunkIndex() + chunkindex[b'\xbb'*32] = (1, 100, 50) + chunkindex[b'\xaa'*32] = (1, 200, 100) + + # marker exists + items = list(chunkindex.iteritems(marker=b'\xbb'*32)) + assert len(items) == 1 + assert items[0][0] == b'\xaa'*32 + + # marker does not exist + with pytest.raises(KeyError, match="marker not found"): + list(chunkindex.iteritems(marker=b'\xcc'*32))