fix(format): validate chunk dimensions and chunk index offsets like libhdf5
A chunk dimension of 0 read a dataset as all fill values, 0x80000000 made
an 8 GiB chunk, and a chunk dimension the chunk index's offsets are not
multiples of read chunks at the wrong place (cve-2018-11205). libhdf5
refuses all of these; now so does clawhdf5:
- DataLayout::parse (H5O__layout_decode): no chunk dimension 0 ("bad chunk
dimension value"), at most 33 dimensions, and before layout v4 at least
2 ("bad dimensions for chunked storage"). New
FormatError::InvalidChunkDimensions.
- Reading a chunked dataset (H5D__chunk_init / H5D__chunk_set_sizes): the
chunk rank must match the dataspace's and a chunk must be under 4 GiB.
One chunked_read::chunk_geometry replaces the four copies of the rank
check.
- v1 B-tree chunk index (H5D__btree_decode_key): every key's offsets must
be multiples of the chunk dimensions, including the keys that only bound
a node, which is where cve-2018-11205's bad dimension shows. New
chunked_read::collect_chunk_info_checked; the chunked read and selection
paths use it.
New interop test header_validation_interop.rs: h5py writes chunked files
(layout v3 and v4), the script corrupts the chunk dimension, and
clawhdf5 must read exactly the copies h5py reads.
Conformance (cached corpus, tank): 570 ok, unchanged; cve-2018-11205 now
refuses the dataset h5py refuses; six more objects that already failed now
fail with libhdf5's reason.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -360,6 +360,7 @@ pub fn read_raw_data_selection(
|
||||
chunk_index_type,
|
||||
..
|
||||
} => {
|
||||
crate::chunked_read::chunk_geometry(chunk_dimensions, dataspace, elem_size)?;
|
||||
// For chunked data, only read chunks that intersect the selection
|
||||
let chunk_dims: Vec<u64> = chunk_dimensions.iter().map(|&d| d as u64).collect();
|
||||
let rank = dims.len();
|
||||
@@ -400,10 +401,10 @@ pub fn read_raw_data_selection(
|
||||
} else {
|
||||
// v3: B-tree v1
|
||||
if let Some(addr) = btree_address {
|
||||
crate::chunked_read::collect_chunk_info(
|
||||
crate::chunked_read::collect_chunk_info_checked(
|
||||
file_data,
|
||||
*addr,
|
||||
rank + 1,
|
||||
chunk_dimensions,
|
||||
offset_size,
|
||||
length_size,
|
||||
)?
|
||||
|
||||
Reference in New Issue
Block a user