fix(format): a VL element at the undefined heap address is an error
libhdf5 fails to read a VL element whose global heap address is
undefined (all 0xff), even at length 0 ("addr undefined"); we returned
"" (or an empty sequence) in every reader. Checked with h5py first:
libhdf5 writes a null element with address 0, which still reads as
empty, and h5py writes "" as a zero-size heap object at a real address,
so no file they write relies on the old behaviour. read_vl_bytes now
treats address 0 as null whatever the length, as VlResolver does.
Tests, each failing before: vl_data unit test (8- and 4-byte offsets,
lengths 0 and 1); clawhdf5 vl_data_interop
a_vl_element_at_the_undefined_heap_address_fails_like_h5py (also checks
where h5py writes ""); h5rs dump --json and check --data on the patched
`undef` dataset; clawhdf5-wasm vl_strings.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -828,7 +828,8 @@ fn dump_prints_vl_data_like_h5dump() {
|
||||
|
||||
/// `dump --json` gives the values h5py reads, element by element; and an
|
||||
/// element whose heap object is not its length × base size is an error, as
|
||||
/// in h5py, not a truncated value (it printed "cde" and (1, 2)).
|
||||
/// in h5py, not a truncated value (it printed "cde" and (1, 2)); so is a
|
||||
/// length-0 element at the undefined heap address (it printed "").
|
||||
#[test]
|
||||
fn dump_json_vl_values_match_h5py() {
|
||||
let Some(f) = generate_vl() else { return };
|
||||
@@ -860,7 +861,12 @@ fn dump_json_vl_values_match_h5py() {
|
||||
let e = g["error"]
|
||||
.as_str()
|
||||
.unwrap_or_else(|| panic!("{bad}: {path}: {g}"));
|
||||
assert!(e.contains("holds"), "{bad}: {path}: {e}");
|
||||
let why = if path == "/undef" {
|
||||
"undefined"
|
||||
} else {
|
||||
"holds"
|
||||
};
|
||||
assert!(e.contains(why), "{bad}: {path}: {e}");
|
||||
} else {
|
||||
assert_eq!(g, w, "{bad}: {path}");
|
||||
}
|
||||
@@ -871,7 +877,8 @@ fn dump_json_vl_values_match_h5py() {
|
||||
|
||||
/// `check --data` holds VL elements to libhdf5's rule: a heap object whose
|
||||
/// size is not exactly the element's length × base size is a problem (it
|
||||
/// only caught objects shorter than the element).
|
||||
/// only caught objects shorter than the element), and so is an element at
|
||||
/// the undefined heap address.
|
||||
#[test]
|
||||
fn check_data_flags_mis_sized_vl_heap_objects() {
|
||||
let Some(f) = generate_vl() else { return };
|
||||
@@ -893,5 +900,11 @@ fn check_data_flags_mis_sized_vl_heap_objects() {
|
||||
assert!(s.contains(&want), "bad{tag}: no {want:?} in\n{s}");
|
||||
assert!(s.contains(what), "bad{tag}: {s}");
|
||||
}
|
||||
// A length-0 element at the undefined heap address: libhdf5 fails
|
||||
// to read it; check skipped it.
|
||||
let undef: u64 = if tag == "8" { u64::MAX } else { 0xffff_ffff };
|
||||
let want = format!("problem: {undef:#x} /undef: variable-length data: global heap:");
|
||||
assert!(s.contains(&want), "bad{tag}: no {want:?} in\n{s}");
|
||||
assert!(s.contains("undefined global heap address"), "bad{tag}: {s}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user