fix(format): honour unknown-message flags the way libhdf5 does
The object header parser failed on an unknown message with flag bit 3 set and ignored bit 7. Per the spec, bit 3 means "fail if unknown and the file is opened for writing" and bit 7 "fail if unknown, always". The parser only reads, so it now ignores bit 3 (as libhdf5 does for a read-only open) and refuses bit 7, in v1 headers, v2 headers and their continuation chunks. On libhdf5's conformance file tbogus.h5 (added as a fixture) we used to refuse Dataset2 and open Dataset3; we now match libhdf5: Dataset1, 2, 4 and 5 open, Dataset3 is refused. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
BIN
Binary file not shown.
@@ -563,3 +563,37 @@ fn slash_in_a_group_or_dataset_name_is_an_error() {
|
||||
let bytes = fw.finish().unwrap();
|
||||
header_at(&bytes, "g/c");
|
||||
}
|
||||
|
||||
// ---- 7. unknown-message flags on read ----
|
||||
|
||||
#[test]
|
||||
fn unknown_message_flags_follow_libhdf5_on_tbogus() {
|
||||
// libhdf5's own test file (test/testfiles/tbogus.h5): datasets carrying
|
||||
// an unknown message with various flags. libhdf5 (read-only) opens
|
||||
// Dataset1, 2, 4 and 5 and refuses Dataset3 ("unknown message with 'fail
|
||||
// if unknown' flag found"). We used to refuse Dataset2 (bit 3, which only
|
||||
// applies when writing) and open Dataset3 (bit 7, fail always).
|
||||
let bytes = include_bytes!("fixtures/tbogus.h5");
|
||||
let sig = signature::find_signature(bytes).unwrap();
|
||||
let sb = Superblock::parse(bytes, sig).unwrap();
|
||||
for (name, readable) in [
|
||||
("Dataset1", true),
|
||||
("Dataset2", true),
|
||||
("Dataset3", false),
|
||||
("Dataset4", true),
|
||||
("Dataset5", true),
|
||||
] {
|
||||
let addr = resolve_path_any(bytes, &sb, name).unwrap();
|
||||
let parsed = ObjectHeader::parse(bytes, addr as usize, sb.offset_size, sb.length_size);
|
||||
match parsed {
|
||||
Ok(_) => assert!(readable, "{name} must be refused"),
|
||||
Err(e) => {
|
||||
assert!(!readable, "{name} must be readable, got {e:?}");
|
||||
assert!(matches!(
|
||||
e,
|
||||
clawhdf5_format::error::FormatError::UnsupportedMessage(_)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user