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:
@@ -6,6 +6,7 @@ use alloc::{collections::BTreeMap, format, string::String, vec, vec::Vec};
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::addr::to_usize;
|
||||
#[cfg(feature = "std")]
|
||||
use crate::chunk_cache::ChunkCache;
|
||||
use crate::chunked_read::read_chunked_data;
|
||||
@@ -117,7 +118,7 @@ pub fn read_raw_data_zerocopy<'a>(
|
||||
dataspace: &Dataspace,
|
||||
datatype: &Datatype,
|
||||
) -> Result<Option<&'a [u8]>, FormatError> {
|
||||
let num_elements = dataspace.num_elements() as usize;
|
||||
let num_elements = to_usize(dataspace.num_elements())?;
|
||||
let elem_size = datatype.type_size() as usize;
|
||||
let expected_size = num_elements.checked_mul(elem_size).ok_or_else(|| {
|
||||
FormatError::Overflow(format!(
|
||||
@@ -128,7 +129,7 @@ pub fn read_raw_data_zerocopy<'a>(
|
||||
match layout {
|
||||
DataLayout::Contiguous { address, size } => {
|
||||
let addr = address.ok_or(FormatError::NoDataAllocated)?;
|
||||
let addr = addr as usize;
|
||||
let addr = to_usize(addr)?;
|
||||
let sz = contiguous_read_len(*size, expected_size)?;
|
||||
ensure_len(file_data, addr, sz)?;
|
||||
Ok(Some(&file_data[addr..addr + sz]))
|
||||
@@ -219,7 +220,7 @@ fn read_raw_data_full_impl(
|
||||
length_size: u8,
|
||||
resolver: Option<&VdsSourceResolver>,
|
||||
) -> Result<Vec<u8>, FormatError> {
|
||||
let num_elements = dataspace.num_elements() as usize;
|
||||
let num_elements = to_usize(dataspace.num_elements())?;
|
||||
let elem_size = datatype.type_size() as usize;
|
||||
let expected_size = num_elements.checked_mul(elem_size).ok_or_else(|| {
|
||||
FormatError::Overflow(format!(
|
||||
@@ -239,7 +240,7 @@ fn read_raw_data_full_impl(
|
||||
}
|
||||
DataLayout::Contiguous { address, size } => {
|
||||
let addr = address.ok_or(FormatError::NoDataAllocated)?;
|
||||
let addr = addr as usize;
|
||||
let addr = to_usize(addr)?;
|
||||
let sz = contiguous_read_len(*size, expected_size)?;
|
||||
ensure_len(file_data, addr, sz)?;
|
||||
let mut out = crate::bulk_alloc::vec_for_bulk(sz);
|
||||
@@ -582,7 +583,7 @@ pub fn extract_selection_from_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] * to_usize(dims[i + 1])?;
|
||||
}
|
||||
|
||||
let mut output = Vec::with_capacity(pts.len() * elem_size);
|
||||
@@ -590,8 +591,8 @@ pub fn extract_selection_from_buffer(
|
||||
let flat: usize = pt
|
||||
.iter()
|
||||
.zip(ds_strides.iter())
|
||||
.map(|(&p, &s)| p as usize * s)
|
||||
.sum();
|
||||
.map(|(&p, &s)| Ok(to_usize(p)? * s))
|
||||
.sum::<Result<usize, FormatError>>()?;
|
||||
let src = flat * elem_size;
|
||||
if src + elem_size <= full_data.len() {
|
||||
output.extend_from_slice(&full_data[src..src + elem_size]);
|
||||
@@ -1341,7 +1342,7 @@ pub fn read_compound_fields(
|
||||
let mut fields = Vec::with_capacity(members.len());
|
||||
for m in members {
|
||||
let field_size = m.datatype.type_size() as usize;
|
||||
let offset = m.byte_offset as usize;
|
||||
let offset = to_usize(m.byte_offset)?;
|
||||
if offset
|
||||
.checked_add(field_size)
|
||||
.is_none_or(|end| end > elem_size)
|
||||
|
||||
Reference in New Issue
Block a user