Files
rustfs/crates
Zhengchao An df9cbc4ed1 fix(ecstore): validate erasure distribution values to avoid shuffle index panic (#4427)
fix(ecstore): validate erasure distribution values to avoid shuffle index panic (backlog#949)

The element values of `erasure.distribution` read from `xl.meta` were never
range-checked. `FileInfo::is_valid()` and `MetaObjectV1::valid()` only verified
`distribution.len()` and the `erasure.index` bound, not that each distribution
value is a valid 1-based slot in `[1, N]`. The metadata shuffle helpers then use
these values directly as `distribution[k] - 1` indices, so a corrupt or
adversarial `xl.meta` carrying a `0` (usize underflow) or a value greater than N
(out-of-bounds) triggers a panic in the shuffle path, turning bad-disk metadata
that erasure coding is meant to tolerate into a request/task crash.

Fix, two layers:
- Validate distribution values at metadata acceptance: `is_valid_distribution`
  now requires the distribution to be a permutation of `1..=N` (correct length,
  every value in range, no duplicates). `FileInfo::is_valid()` and
  `MetaObjectV1::valid()` use it, so `find_file_info_in_quorum` rejects corrupt
  metadata and it surfaces as a clean `ErasureReadQuorum` error instead of an
  index path.
- Defensive indexing in the shuffle helpers (`shuffle_disks_and_parts_metadata`,
  `_by_index`, `_by_index_owned`, `shuffle_parts_metadata`, `shuffle_disks`,
  `shuffle_check_parts`): out-of-range distribution values are skipped via
  `checked_sub(1)` + bounds-checked slot access instead of a bare `idx - 1`
  index, matching the existing pattern in
  `collect_inline_data_shard_fileinfos_by_index`.

Regression tests: `is_valid_distribution`/`is_valid`/`valid` reject distributions
containing `0`, values greater than N, duplicates, and wrong length while
accepting valid permutations; the shuffle helpers no longer panic on corrupt
distributions and preserve output length.

Refs: https://github.com/rustfs/backlog/issues/949
2026-07-08 15:02:16 +08:00
..