format: no truncating u64 -> usize casts
Every `u64 as usize` cast in clawhdf5-format (115 on wasm32) now goes through addr::to_usize for values read from the file — addresses, lengths, counts, dimensions: FormatError::Overflow where the value does not fit instead of wrapping onto another part of the file on a 32-bit target — or addr::saturating_usize for counts bounded by something in memory (codec progress counters, writer sizes), which fail a bounds check or allocation rather than wrap. A chunk whose offset does not fit lies outside the dataset and is skipped; partial reads treat such an offset as out of the buffers. On 64-bit targets nothing changes. scripts/check-32bit-casts.sh (run by ci-test.sh) lints the wasm32 build with clippy's cast_possible_truncation and fails on any u64 -> usize finding; before this commit it listed 115. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
use crate::addr::saturating_usize;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{format, vec, vec::Vec};
|
||||
|
||||
@@ -414,18 +415,18 @@ pub fn split_into_chunks(
|
||||
// Dataset strides (row-major)
|
||||
let mut ds_strides = vec![1usize; rank];
|
||||
for i in (0..rank.saturating_sub(1)).rev() {
|
||||
ds_strides[i] = ds_strides[i + 1] * shape[i + 1] as usize;
|
||||
ds_strides[i] = ds_strides[i + 1] * saturating_usize(shape[i + 1]);
|
||||
}
|
||||
|
||||
// Chunk strides
|
||||
let mut chunk_strides = vec![1usize; rank];
|
||||
for i in (0..rank.saturating_sub(1)).rev() {
|
||||
chunk_strides[i] = chunk_strides[i + 1] * chunk_dims[i + 1] as usize;
|
||||
chunk_strides[i] = chunk_strides[i + 1] * saturating_usize(chunk_dims[i + 1]);
|
||||
}
|
||||
|
||||
let chunk_total_elements: usize = chunk_dims.iter().map(|&d| d as usize).product();
|
||||
let chunk_total_elements: usize = chunk_dims.iter().map(|&d| saturating_usize(d)).product();
|
||||
|
||||
let mut result = Vec::with_capacity(total_chunks as usize);
|
||||
let mut result = Vec::with_capacity(saturating_usize(total_chunks));
|
||||
|
||||
for linear_idx in 0..total_chunks {
|
||||
// Convert linear index to chunk grid coordinates
|
||||
@@ -453,8 +454,8 @@ pub fn split_into_chunks(
|
||||
let coord_in_chunk = remaining_idx / chunk_strides[d];
|
||||
remaining_idx %= chunk_strides[d];
|
||||
|
||||
let global_coord = offsets[d] as usize + coord_in_chunk;
|
||||
if global_coord >= shape[d] as usize {
|
||||
let global_coord = saturating_usize(offsets[d]) + coord_in_chunk;
|
||||
if global_coord >= saturating_usize(shape[d]) {
|
||||
out_of_bounds = true;
|
||||
break;
|
||||
}
|
||||
@@ -1036,7 +1037,7 @@ impl ChunkIndexPlan {
|
||||
Ok(Self::SingleChunk)
|
||||
} else {
|
||||
let grid = ChunkGrid::fixed_array(shape, Some(max), chunk_dims)?;
|
||||
Ok(Self::FixedArray(grid, nslots as usize))
|
||||
Ok(Self::FixedArray(grid, saturating_usize(nslots)))
|
||||
}
|
||||
}
|
||||
1 => Ok(Self::ExtensibleArray(ChunkGrid::extensible_array(
|
||||
@@ -1251,7 +1252,7 @@ pub fn write_selection_to_buffer(
|
||||
let rank = dims.len();
|
||||
let mut ds_strides = vec![1usize; rank];
|
||||
for i in (0..rank.saturating_sub(1)).rev() {
|
||||
ds_strides[i] = ds_strides[i + 1] * dims[i + 1] as usize;
|
||||
ds_strides[i] = ds_strides[i + 1] * saturating_usize(dims[i + 1]);
|
||||
}
|
||||
|
||||
let mut src_offset = 0usize;
|
||||
@@ -1301,7 +1302,7 @@ pub fn write_selection_to_buffer(
|
||||
buffer,
|
||||
new_data,
|
||||
src_offset,
|
||||
current_ds_offset + coord as usize * ds_strides[d],
|
||||
current_ds_offset + saturating_usize(coord) * ds_strides[d],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1328,14 +1329,14 @@ pub fn write_selection_to_buffer(
|
||||
let rank = dims.len();
|
||||
let mut ds_strides = vec![1usize; rank];
|
||||
for i in (0..rank.saturating_sub(1)).rev() {
|
||||
ds_strides[i] = ds_strides[i + 1] * dims[i + 1] as usize;
|
||||
ds_strides[i] = ds_strides[i + 1] * saturating_usize(dims[i + 1]);
|
||||
}
|
||||
|
||||
for (pi, pt) in pts.iter().enumerate() {
|
||||
let flat: usize = pt
|
||||
.iter()
|
||||
.zip(ds_strides.iter())
|
||||
.map(|(&p, &s)| p as usize * s)
|
||||
.map(|(&p, &s)| saturating_usize(p) * s)
|
||||
.sum();
|
||||
let dst = flat * elem_size;
|
||||
let src = pi * elem_size;
|
||||
|
||||
Reference in New Issue
Block a user