h5rs tools, browser reader, libhdf5 header checks, plugin filters, concurrency benchmark #14
@@ -421,6 +421,13 @@ impl ObjectHeader {
|
||||
};
|
||||
pos += msg_header_size;
|
||||
|
||||
// `end` is where the messages stop and the checksum starts.
|
||||
// libhdf5 bounds a message by the chunk including its checksum,
|
||||
// but a message that runs into the checksum still fails there:
|
||||
// its loop stops at the checksum, and reading the checksum from
|
||||
// past its start overruns the chunk ("ran off end of input
|
||||
// buffer while decoding"). Both refuse it; only the text
|
||||
// differs.
|
||||
if msg_data_size > end - pos {
|
||||
return Err(FormatError::InvalidObjectHeader(
|
||||
"message size exceeds buffer end",
|
||||
|
||||
@@ -252,6 +252,54 @@ for libver in ("earliest", "latest"):
|
||||
}
|
||||
}
|
||||
|
||||
/// A v2 object header message whose size runs past the messages into the
|
||||
/// chunk's checksum is refused by libhdf5 whether it runs 1 byte or more
|
||||
/// into the checksum (its loop stops at the checksum, and then the checksum
|
||||
/// read and the size check fail), so it is refused here too.
|
||||
#[test]
|
||||
fn v2_header_message_running_into_the_checksum_is_refused() {
|
||||
skip_if_no_python!();
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let body = format!(
|
||||
"{FIX_OHDR_PY}{}",
|
||||
r#"
|
||||
good = os.path.join(d, "good.h5")
|
||||
with h5py.File(good, "w", libver="latest") as f:
|
||||
f.create_dataset("d", data=np.arange(4, dtype="<i4"))
|
||||
raw = bytearray(open(good, "rb").read())
|
||||
off = raw.rfind(b"OHDR")
|
||||
flags = raw[off + 5]; p = off + 6
|
||||
if flags & 0x20: p += 16
|
||||
if flags & 0x10: p += 4
|
||||
width = 1 << (flags & 3)
|
||||
end = p + width + int.from_bytes(raw[p:p + width], "little"); p += width
|
||||
hdr = 6 if flags & 0x04 else 4
|
||||
last = p
|
||||
while p + hdr <= end:
|
||||
last = p
|
||||
p += hdr + int.from_bytes(raw[p + 1:p + 3], "little")
|
||||
assert p == end
|
||||
size = int.from_bytes(raw[last + 1:last + 3], "little")
|
||||
for k in (1, 4, 5):
|
||||
bad = bytearray(raw)
|
||||
bad[last + 1:last + 3] = (size + k).to_bytes(2, "little")
|
||||
fix_ohdr(bad, off)
|
||||
open(os.path.join(d, f"into_checksum_{k}.h5"), "wb").write(bad)
|
||||
"#
|
||||
);
|
||||
let verdicts = h5py_verdicts(dir.path(), &body);
|
||||
assert_agrees_with_h5py(
|
||||
dir.path(),
|
||||
&verdicts,
|
||||
&[
|
||||
"good ok",
|
||||
"into_checksum_1 ERROR",
|
||||
"into_checksum_4 ERROR",
|
||||
"into_checksum_5 ERROR",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncated_files_are_refused_and_nothing_past_the_end_of_file_is_read() {
|
||||
skip_if_no_python!();
|
||||
|
||||
Reference in New Issue
Block a user