mirror of https://github.com/borgbackup/borg.git
hashindex: read/write: use hash_part for HashHeader
This commit is contained in:
parent
f59affe585
commit
d463dd89aa
|
@ -291,6 +291,20 @@ hashindex_read(PyObject *file_py)
|
|||
goto fail_decref_header;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash the header
|
||||
* If the header is corrupted this bails before doing something stupid (like allocating 3.8 TB of memory)
|
||||
*/
|
||||
Py_XDECREF(PyObject_CallMethod(file_py, "hash_part", "s", "HashHeader"));
|
||||
if(PyErr_Occurred()) {
|
||||
if(PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
/* Be able to work with regular file objects which do not have a hash_part method. */
|
||||
PyErr_Clear();
|
||||
} else {
|
||||
goto fail_decref_header;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find length of file */
|
||||
length_object = PyObject_CallMethod(file_py, "seek", "ni", (Py_ssize_t)0, SEEK_END);
|
||||
if(PyErr_Occurred()) {
|
||||
|
@ -473,6 +487,19 @@ hashindex_write(HashIndex *index, PyObject *file_py)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash the header
|
||||
*/
|
||||
Py_XDECREF(PyObject_CallMethod(file_py, "hash_part", "s", "HashHeader"));
|
||||
if(PyErr_Occurred()) {
|
||||
if(PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
/* Be able to work with regular file objects which do not have a hash_part method. */
|
||||
PyErr_Clear();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: explicitly construct view; BuildValue can convert (pointer, length) to Python objects, but copies them for doing so */
|
||||
buckets_view = PyMemoryView_FromMemory((char*)index->buckets, buckets_length, PyBUF_READ);
|
||||
if(!buckets_view) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import zlib
|
|||
|
||||
from ..hashindex import NSIndex, ChunkIndex
|
||||
from .. import hashindex
|
||||
from ..crypto.file_integrity import IntegrityCheckedFile, FileIntegrityError
|
||||
from . import BaseTestCase
|
||||
|
||||
# Note: these tests are part of the self test, do not use or import py.test functionality here.
|
||||
|
@ -319,6 +320,27 @@ class HashIndexDataTestCase(BaseTestCase):
|
|||
assert idx1[H(3)] == (ChunkIndex.MAX_VALUE, 6, 7)
|
||||
|
||||
|
||||
class HashIndexIntegrityTestCase(HashIndexDataTestCase):
|
||||
def write_integrity_checked_index(self, tempdir):
|
||||
idx = self._deserialize_hashindex(self.HASHINDEX)
|
||||
file = os.path.join(tempdir, 'idx')
|
||||
with IntegrityCheckedFile(path=file, write=True) as fd:
|
||||
idx.write(fd)
|
||||
integrity_data = fd.integrity_data
|
||||
assert 'final' in integrity_data
|
||||
assert 'HashHeader' in integrity_data
|
||||
return file, integrity_data
|
||||
|
||||
def test_integrity_checked_file(self):
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
file, integrity_data = self.write_integrity_checked_index(tempdir)
|
||||
with open(file, 'r+b') as fd:
|
||||
fd.write(b'Foo')
|
||||
with self.assert_raises(FileIntegrityError):
|
||||
with IntegrityCheckedFile(path=file, write=False, integrity_data=integrity_data) as fd:
|
||||
ChunkIndex.read(fd)
|
||||
|
||||
|
||||
class NSIndexTestCase(BaseTestCase):
|
||||
def test_nsindex_segment_limit(self):
|
||||
idx = NSIndex()
|
||||
|
|
Loading…
Reference in New Issue