h5rs tools, browser reader, libhdf5 header checks, plugin filters, concurrency benchmark #14
@@ -421,6 +421,13 @@ impl ObjectHeader {
|
|||||||
};
|
};
|
||||||
pos += msg_header_size;
|
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 {
|
if msg_data_size > end - pos {
|
||||||
return Err(FormatError::InvalidObjectHeader(
|
return Err(FormatError::InvalidObjectHeader(
|
||||||
"message size exceeds buffer end",
|
"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]
|
#[test]
|
||||||
fn truncated_files_are_refused_and_nothing_past_the_end_of_file_is_read() {
|
fn truncated_files_are_refused_and_nothing_past_the_end_of_file_is_read() {
|
||||||
skip_if_no_python!();
|
skip_if_no_python!();
|
||||||
|
|||||||
Reference in New Issue
Block a user