fix: refuse numeric types with unusually many unused bits in v1 headers

libhdf5 1.14.4+ treats an integer, float or bit field wider than a byte
whose precision and offset leave more than half its bits unused as
corruption when the type sits in a header without a checksum (version 1),
unless the file is opened with H5Pset_relax_file_integrity_checks
(H5T_is_numeric_with_unusual_unused_bits). clawhdf5 read such types,
e.g. a 3-bit integer in 4 bytes (cve-2024-29162) or a 32-bit float in
65525 bytes (cve-2024-32614, tmisc38a.h5).

New Datatype::check_unused_bits (recursive) and Datatype::parse_in_header,
which applies it for version-1 headers. Dataset datatypes (facade File,
LazyFile, MmapFile; clawhdf5-io VOL, MPI VOL, async reader; the
conformance probe) and compact attributes in version-1 headers use it.

Conformance (cached corpus, tank): 570 ok, unchanged; cve-2024-29162,
cve-2024-32614 and tmisc38a.h5 now refuse the object h5py refuses, and
tmisc38b.h5 / unknown-1.h5 now fail with libhdf5's reason.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 00:12:04 -05:00
co-authored by Claude Opus 5.5
parent 3cf8cd86f2
commit a5ca970015
9 changed files with 117 additions and 11 deletions
+1 -1
View File
@@ -312,7 +312,7 @@ impl AsyncHDF5File {
let dt_msg =
find_msg(&header, MessageType::Datatype).ok_or(FormatError::DatasetMissingData)?;
let (datatype, _) = Datatype::parse(&dt_msg.data)?;
let (datatype, _) = Datatype::parse_in_header(&dt_msg.data, header.version)?;
let ds_msg =
find_msg(&header, MessageType::Dataspace).ok_or(FormatError::DatasetMissingShape)?;