You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "techgopal (via GitHub)" <gi...@apache.org> on 2026/10/18 16:00:09 UTC
[I] parquet: panic (BitChunks "offset + len out of bounds") reading definition levels with a bit-packed run longer than the page data [arrow-rs]
techgopal opened a new issue, #11691:
URL: https://github.com/apache/arrow-rs/issues/11691
### Describe the bug
Reading a nullable column whose definition levels contain a bit-packed run that is longer than the remaining level data panics in `arrow-buffer` instead of returning an error.
`PackedDecoder::next_rle_block` (`parquet/src/arrow/record_reader/definition_levels.rs`) sets `packed_count` from the run header, and `PackedDecoder::read` then calls
```rust
buffer.append_packed_range(offset..offset + to_read, self.data.as_ref());
```
without checking that `self.data` holds `ceil((offset + to_read) / 8)` bytes. `BooleanBufferBuilder::append_packed_range` documents that it panics in that case, and it does, from `BitChunks::new`:
```
assert!(ceil(end, 8) <= buffer.len(), "offset + len out of bounds");
```
This is different from #11516 / #11517 (overflow of the run length): here the run length is small and valid, it just exceeds the bytes available in the page.
### To Reproduce
With `parquet = "60.0.0"`, `arrow-array = "60.0.0"`, `arrow-schema = "60.0.0"`, `bytes = "1"`:
```rust
use std::sync::Arc;
use arrow_array::{Int32Array, RecordBatch};
use arrow_schema::{DataType, Field, Schema};
use bytes::Bytes;
use parquet::arrow::arrow_reader::ParquetRecordBatchReaderBuilder;
use parquet::arrow::ArrowWriter;
use parquet::file::properties::WriterProperties;
fn main() {
// A nullable INT32 column with every other value null: the data page
// (v1, uncompressed, plain) starts with the definition levels as
// [4-byte length = 127][bit-packed header 0x7F (63 groups = 504 levels)][63 bytes]...
let array: Int32Array = (0..1000).map(|i| (i % 2 == 0).then_some(i)).collect();
let schema = Arc::new(Schema::new(vec![Field::new("c", DataType::Int32, true)]));
let batch = RecordBatch::try_new(schema.clone(), vec![Arc::new(array)]).unwrap();
let props = WriterProperties::builder().set_dictionary_enabled(false).build();
let mut buf = Vec::new();
let mut writer = ArrowWriter::try_new(&mut buf, schema, Some(props)).unwrap();
writer.write(&batch).unwrap();
writer.close().unwrap();
// Shrink the definition-level length prefix from 127 to 3 bytes; the
// first bit-packed run header still claims 504 levels.
let pattern = [0x7F, 0, 0, 0, 0x7F, 0x55];
let pos = buf.windows(pattern.len()).position(|w| w == pattern).expect("pattern");
buf[pos] = 3;
let reader = ParquetRecordBatchReaderBuilder::try_new(Bytes::from(buf))
.unwrap()
.build()
.unwrap();
for batch in reader {
println!("{:?}", batch.map(|b| b.num_rows()));
}
}
```
Output (debug and release):
```
thread 'main' panicked at arrow-buffer-60.0.0/src/util/bit_chunk_iterator.rs:235:9:
offset + len out of bounds
```
Backtrace (abridged):
```
arrow_buffer::util::bit_chunk_iterator::BitChunks::new
arrow_buffer::util::bit_util::byte_aligned_bitwise_bin_op_helper
arrow_buffer::util::bit_util::apply_bitwise_binary_op
arrow_buffer::builder::boolean::BooleanBufferBuilder::append_packed_range
parquet::arrow::record_reader::definition_levels::PackedDecoder::read
<parquet::arrow::record_reader::definition_levels::DefinitionLevelBufferDecoder as DefinitionLevelDecoder>::read_def_levels
parquet::column::reader::GenericColumnReader<R,D,V>::read_records_with_reservation
...
```
The same panic is reachable through `ParquetPushDecoder::try_decode`.
### Expected behavior
The reader returns a `ParquetError` (e.g. unexpected end of definition level data) instead of panicking.
### Additional context
- Reproduces with `parquet` / `arrow-buffer` 60.0.0 and on `main` at 33d338ddf (`definition_levels.rs:446`).
- Found while fuzzing a Parquet reader built on arrow-rs. Related: #11516, #9742.
--
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.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org