format: checked chunk addresses on the parallel read path

Three `chunk_info.address as usize` casts behind the `parallel` feature
survived the conversion, because check-32bit-casts.sh linted only default
features plus plugin-filters. On a 32-bit target with rayon a chunk address
past 4 GiB still wrapped onto another part of the file. They go through
addr::to_usize now, and the lane index (h % n, always < n) through
saturating_usize.

The script now lints no default features, default features, and every
optional feature but szip (wasm32; the set with zstd, which does not build
for wasm32, on the host, where the lint reports the same casts). With the
old parallel_read.rs/lane_partition.rs it fails listing the four casts; the
old script passed them. CHANGELOG and the design note give the exact count
(119) and what is not covered.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 14:08:57 -05:00
co-authored by Claude Opus 5.5
parent 92c8285549
commit b6cbd2319f
5 changed files with 68 additions and 25 deletions
+4 -3
View File
@@ -7,6 +7,7 @@
//! The lane assignment is seeded by dataset metadata so repeated reads of
//! the same region produce identical partitions (cache-friendly, reproducible).
use crate::addr::to_usize;
use crate::chunked_read::ChunkInfo;
use crate::error::FormatError;
use crate::filter_pipeline::FilterPipeline;
@@ -210,7 +211,7 @@ pub fn decompress_chunks_lane_partitioned(
for &index in &indices {
let chunk_info = &chunks[index];
let c_addr = chunk_info.address as usize;
let c_addr = to_usize(chunk_info.address)?;
let size = chunk_info.chunk_size as usize;
if c_addr
@@ -288,7 +289,7 @@ pub fn decompress_chunks_parallel(
.par_iter()
.enumerate()
.map(|(index, chunk_info)| {
let c_addr = chunk_info.address as usize;
let c_addr = to_usize(chunk_info.address)?;
let size = chunk_info.chunk_size as usize;
if c_addr
.checked_add(size)
@@ -332,7 +333,7 @@ pub fn decompress_chunks_sequential(
) -> Result<Vec<Vec<u8>>, FormatError> {
let mut result = Vec::with_capacity(chunks.len());
for chunk_info in chunks {
let c_addr = chunk_info.address as usize;
let c_addr = to_usize(chunk_info.address)?;
let size = chunk_info.chunk_size as usize;
if c_addr
.checked_add(size)