conformance: report a cache image libhdf5 cannot load where it does

libhdf5 loads a metadata cache image when it first reads metadata (the
root group), not at open, so for cve-2025-6269-1..4 and cve-2025-6516 (all
corrupt images) h5py opens the file and fails on "/". The probe reported
the image's error as an open error, which made those files our-errors;
it now records it on the root object, where h5py reports it. File::open
still refuses such a file outright: nothing in it can be read.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 10:38:50 -05:00
co-authored by Claude Opus 5.5
parent 6b3d003950
commit f512bf3d09
+26 -6
View File
@@ -712,18 +712,35 @@ fn main() {
return;
}
};
// libhdf5 decodes the superblock extension at open, and loads a
// metadata cache image over the file's own metadata.
let view = match guarded(|| {
clawhdf5_format::superblock_ext::metadata_view(hdf5, &sb).map_err(e)
}) {
Ok(v) => v,
// libhdf5 decodes the superblock extension at open (File::open does
// the same), and loads a metadata cache image over the file's own
// metadata. It loads the image only when it first reads metadata — the
// root group — so a file whose image it cannot load still opens and
// every object fails; File::open refuses such a file outright. The
// probe records the image's error where libhdf5 reports it.
use clawhdf5_format::superblock_ext;
let ext = match guarded(|| superblock_ext::read_superblock_extension(hdf5, &sb).map_err(e)) {
Ok(x) => x,
Err(msg) => {
top.insert("open_error".into(), Value::String(msg));
println!("{}", Value::Object(top));
return;
}
};
let mut image_error = None;
let view = match ext.and_then(|x| x.cache_image) {
None => None,
Some(loc) => match guarded(|| {
superblock_ext::apply_cache_image(hdf5, loc, sb.offset_size, sb.length_size)
.map_err(e)
}) {
Ok(v) => Some(v),
Err(msg) => {
image_error = Some(msg);
None
}
},
};
let hdf5: &[u8] = view.as_deref().unwrap_or(hdf5);
top.insert("superblock_version".into(), json!(sb.version));
let ctx = Ctx {
@@ -752,6 +769,9 @@ fn main() {
let mut rec = Map::new();
rec.insert("path".into(), Value::String(p.clone()));
let r = guarded(|| {
if let Some(msg) = &image_error {
return Err(msg.clone());
}
let h = ctx.header(addr)?;
Ok(h)
});