You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "prostomarkeloff (via GitHub)" <gi...@apache.org> on 2026/10/23 16:11:15 UTC

[PR] fix(parquet): avoid false overflow in DeltaBitPackDecoder::skip for INT32 [arrow-rs]

prostomarkeloff opened a new pull request, #11864:
URL: https://github.com/apache/arrow-rs/pull/11864

   Found with [find-dup-defs](https://github.com/prostomarkeloff/find-dup-defs) using its `converge` pass, which reports behavioural divergences between near-duplicate functions. It flagged `DeltaBitPackDecoder`'s `get` and `skip` as near-duplicates that diverge in the `bit_width == 0` arithmetic: `get` advances the value in `T`'s own width, while `skip` does the multiply in `i64` and converts back with `from_i64`.
   
   ## Which issue does this PR close?
   
   None filed yet — happy to open an issue first if that's preferred.
   
   ## Rationale
   
   In the `bit_width == 0` branch, `DeltaBitPackDecoder::skip` advances `last_value` by `n * min_delta`. It computes this product in `i64` and then does `T::T::from_i64(total)`, which returns `None` when the product does not fit in `T` (e.g. `i32`) and surfaces as `General("delta*n overflow in skip")`:
   
   ```rust
   let total = min_delta.wrapping_mul(mini_block_to_skip as i64);
   let step = T::T::from_i64(total)
       .ok_or_else(|| general_err!("delta*n overflow in skip"))?;
   ```
   
   `get()` performs the equivalent arithmetic in `T`'s own width with wrapping and never rejects such data, so `skip()` fails on inputs that `get()` decodes fine. This is reachable whenever a reader skips values in an INT32 `DELTA_BINARY_PACKED` column (e.g. a `RowSelection` or page offset), making otherwise-valid files unreadable along that path.
   
   ## What changes
   
   Do the multiply in `T`'s width with wrapping, matching `get()`: take the count as `T` via `from_usize`, then `self.min_delta.wrapping_mul(&step_count)`.
   
   ## Are there any user-facing changes?
   
   No API change; files that previously errored on skip now decode.
   
   ## Tests
   
   Added four tests in `encodings::decoding::tests` that assert `get()` and `skip()` agree on INT32 data triggering the overflow (large per-step deltas spanning the i32 range; alternating `i32::MIN`/`0`). Each fails before this change and passes after; `cargo test -p parquet --lib encodings::decoding` is green.
   
   Disclosure: parts of this change were generated with the help of an AI tool; I have reviewed the change and the tests and understand each line.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org