parquet: ParquetMetaDataPushDecoder panics (subtract with overflow) when the footer metadata length exceeds the file size
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
Research direction
Start in parquet/src/file/metadata/push_decoder.rs at ParquetMetaDataPushDecoder::try_decode, where the issue shows the unchecked footer length subtraction. Compare its error handling with ParquetMetaDataReader::parse_and_finish on the same malformed 12-byte input. Done when the push decoder returns a ParquetError instead of panicking for an oversized metadata length.
Written by the indexing model from the issue text.
Description
Describe the bug
ParquetMetaDataPushDecoder::try_decode computes the start of the metadata from the footer's metadata length without checking it against the file length (parquet/src/file/metadata/push_decoder.rs):
let metadata_len: u64 = footer_tail.metadata_length() as u64;
let metadata_start = file_len - footer_len - metadata_len;
let metadata_end = metadata_start + metadata_len;
If the footer claims a metadata length larger than file_len - 8, the subtraction underflows:
- with overflow checks (debug builds) it panics with
attempt to subtract with overflow; - without them the value wraps,
metadata_endwraps back to a small value, and the decoder then panics inBytes::slice(range start must not be greater than end).
ParquetMetaDataReader::parse_and_finish on the same bytes returns EOF("Parquet file too small. Size is 12 but need 1008"), so only the push decoder is affected.
To Reproduce
With parquet = "60.0.0":
use parquet::file::metadata::ParquetMetaDataPushDecoder;
use parquet::DecodeResult;
fn main() {
// A 12-byte "file": 4 bytes of data, then a footer whose metadata
// length (1000) is larger than the file.
let mut file = vec![0u8; 4];
file.extend_from_slice(&1000u32.to_le_bytes());
file.extend_from_slice(b"PAR1");
let len = file.len() as u64;
let mut decoder = ParquetMetaDataPushDecoder::try_new(len).unwrap();
decoder.push_range(0..len, file.into()).unwrap();
match decoder.try_decode() {
Ok(DecodeResult::NeedsData(r)) => println!("needs data: {r:?}"),
Ok(DecodeResult::Data(_)) => println!("data"),
Ok(DecodeResult::Finished) => println!("finished"),
Err(e) => println!("error: {e}"),
}
}
Debug build:
thread 'main' panicked at parquet-60.0.0/src/file/metadata/push_decoder.rs:390:42:
attempt to subtract with overflow
Release build:
thread 'main' panicked at bytes-1.12.1/src/bytes.rs:374:28:
range start must not be greater than end: 18446744073709550620 <= 4
(from bytes::Bytes::slice called by ParquetMetaDataPushDecoder::try_decode)
Expected behavior
try_decode returns a ParquetError (like ParquetMetaDataReader, e.g. "file too small ... need N bytes") instead of panicking.
Additional context
- Reproduces with
parquet60.0.0 and onmainat 33d338ddf (push_decoder.rs:430). - Found while fuzzing a Parquet reader built on arrow-rs. Related: #9742, #10563.
- Dominant language
- Rust
- Stars
- 3.6k
- Forks
- 1.4k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 237
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apache/arrow-rs
-
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 Under an hour Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
`substring` errors when the bytes under a null `Utf8` slot would be cut inside a characterPossibly taken @cakeni claimed this 2 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
apache/arrow-rs#11590 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
enhancement parquet
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
Similar issues
-
area:io needs-info needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
bherbruck/solvecraft#3216 · 1 comment ·
-
bug triage/needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
praxis-proxy/grid#412 ·
Maintainers usually reply within 1 day
-
priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
storytold/photocraft#7824 · 1 comment ·
Maintainers usually reply within 1 day
-
area:ui chore could help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 1 day