hashindex: read/write: use hash_part for HashHeader

This commit is contained in:
Marian Beermann 2017-05-25 15:18:45 +02:00
parent f59affe585
commit d463dd89aa
2 changed files with 49 additions and 0 deletions

View File

@ -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) {

View File

@ -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()