You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by al...@apache.org on 2025/09/12 19:54:12 UTC
(arrow-rs) branch main updated: Parquet: Avoid page-size overflows i32 (#8264)
This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 30a779878a Parquet: Avoid page-size overflows i32 (#8264)
30a779878a is described below
commit 30a779878a617116afe73e48ac05abfff0040c6f
Author: mwish <ma...@gmail.com>
AuthorDate: Sat Sep 13 03:54:07 2025 +0800
Parquet: Avoid page-size overflows i32 (#8264)
# Which issue does this PR close?
- Closes #8263
# Rationale for this change
See https://github.com/apache/arrow-rs/issues/8263
# What changes are included in this PR?
Avoid page overflows
# Are these changes tested?
* [x] Will add
# Are there any user-facing changes?
No
---
parquet/src/arrow/arrow_writer/mod.rs | 2 +-
parquet/src/column/page.rs | 40 +++++++++++++++++++++++++++++++++--
parquet/src/file/writer.rs | 2 +-
3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/parquet/src/arrow/arrow_writer/mod.rs b/parquet/src/arrow/arrow_writer/mod.rs
index c6b0b426f9..864c1bf2da 100644
--- a/parquet/src/arrow/arrow_writer/mod.rs
+++ b/parquet/src/arrow/arrow_writer/mod.rs
@@ -571,7 +571,7 @@ impl PageWriter for ArrowPageWriter {
None => page,
};
- let page_header = page.to_thrift_header();
+ let page_header = page.to_thrift_header()?;
let header = {
let mut header = Vec::with_capacity(1024);
diff --git a/parquet/src/column/page.rs b/parquet/src/column/page.rs
index 1dabe6794f..a2f683d71f 100644
--- a/parquet/src/column/page.rs
+++ b/parquet/src/column/page.rs
@@ -196,9 +196,21 @@ impl CompressedPage {
}
/// Returns the thrift page header
- pub(crate) fn to_thrift_header(&self) -> PageHeader {
+ pub(crate) fn to_thrift_header(&self) -> Result<PageHeader> {
let uncompressed_size = self.uncompressed_size();
let compressed_size = self.compressed_size();
+ if uncompressed_size > i32::MAX as usize {
+ return Err(general_err!(
+ "Page uncompressed size overflow: {}",
+ uncompressed_size
+ ));
+ }
+ if compressed_size > i32::MAX as usize {
+ return Err(general_err!(
+ "Page compressed size overflow: {}",
+ compressed_size
+ ));
+ }
let num_values = self.num_values();
let encoding = self.encoding();
let page_type = self.page_type();
@@ -261,7 +273,7 @@ impl CompressedPage {
page_header.dictionary_page_header = Some(dictionary_page_header);
}
}
- page_header
+ Ok(page_header)
}
/// Update the compressed buffer for a page.
@@ -491,4 +503,28 @@ mod tests {
assert_eq!(cpage.encoding(), Encoding::PLAIN);
assert_eq!(cpage.data(), &[0, 1, 2]);
}
+
+ #[test]
+ fn test_compressed_page_uncompressed_size_overflow() {
+ // Test that to_thrift_header fails when uncompressed size exceeds i32::MAX
+ let data_page = Page::DataPage {
+ buf: Bytes::from(vec![0, 1, 2]),
+ num_values: 10,
+ encoding: Encoding::PLAIN,
+ def_level_encoding: Encoding::RLE,
+ rep_level_encoding: Encoding::RLE,
+ statistics: None,
+ };
+
+ // Create a CompressedPage with uncompressed size larger than i32::MAX
+ let uncompressed_size = (i32::MAX as usize) + 1;
+ let cpage = CompressedPage::new(data_page, uncompressed_size);
+
+ // Verify that to_thrift_header returns an error
+ let result = cpage.to_thrift_header();
+ assert!(result.is_err());
+
+ let error_msg = result.unwrap_err().to_string();
+ assert!(error_msg.contains("Page uncompressed size overflow"));
+ }
}
diff --git a/parquet/src/file/writer.rs b/parquet/src/file/writer.rs
index 690efb36f2..9adf67e68b 100644
--- a/parquet/src/file/writer.rs
+++ b/parquet/src/file/writer.rs
@@ -958,7 +958,7 @@ impl<W: Write + Send> PageWriter for SerializedPageWriter<'_, W> {
let page_type = page.page_type();
let start_pos = self.sink.bytes_written() as u64;
- let page_header = page.to_thrift_header();
+ let page_header = page.to_thrift_header()?;
let header_size = self.serialize_page_header(page_header)?;
self.sink.write_all(page.data())?;