This is an automated email from the ASF dual-hosted git repository.
apitrou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 421a475fc5 GH-48900: [C++] Avoid memory blowup with excessive variadic
buffer count in IPC (#48901)
421a475fc5 is described below
commit 421a475fc592041a62bcb1eb906cf0a65e37f1f1
Author: Antoine Pitrou <[email protected]>
AuthorDate: Wed Jan 21 10:16:51 2026 +0100
GH-48900: [C++] Avoid memory blowup with excessive variadic buffer count in
IPC (#48901)
### Rationale for this change
An incorrect variadic buffer count could easily blow up memory when
reserving a vector of Buffers, even though the RecordBatch has a lot less
buffers available.
Reported by OSS-Fuzz at https://issues.oss-fuzz.com/issues/476180608, and
separately by Silas Boch.
### What changes are included in this PR?
Pre-validate the variadic buffer count read from the IPC RecordBatch table.
Initial patch by Silas Boch.
### Are these changes tested?
Yes, by additional fuzz regression file.
### Are there any user-facing changes?
No.
**This PR contains a "Critical Fix".** (If the changes fix either (a) a
security vulnerability, (b) a bug that caused incorrect or invalid data to be
produced, or (c) a bug that causes a crash (even when the API contract is
upheld), please provide explanation. If not, you can remove this.)
* GitHub Issue: #48900
Authored-by: Antoine Pitrou <[email protected]>
Signed-off-by: Antoine Pitrou <[email protected]>
---
cpp/src/arrow/ipc/reader.cc | 18 ++++++++++++------
testing | 2 +-
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/cpp/src/arrow/ipc/reader.cc b/cpp/src/arrow/ipc/reader.cc
index 6a20dbb8c8..8e125fc5ed 100644
--- a/cpp/src/arrow/ipc/reader.cc
+++ b/cpp/src/arrow/ipc/reader.cc
@@ -250,18 +250,24 @@ class ArrayLoader {
}
}
- Result<size_t> GetVariadicCount(int i) {
+ Result<int64_t> GetVariadicCount(int i) {
auto* variadic_counts = metadata_->variadicBufferCounts();
CHECK_FLATBUFFERS_NOT_NULL(variadic_counts,
"RecordBatch.variadicBufferCounts");
if (i >= static_cast<int>(variadic_counts->size())) {
return Status::IOError("variadic_count_index out of range.");
}
int64_t count = variadic_counts->Get(i);
- if (count < 0 || count > std::numeric_limits<int32_t>::max()) {
- return Status::IOError(
- "variadic_count must be representable as a positive int32_t, got ",
count, ".");
+ if (count < 0) {
+ return Status::IOError("variadic buffer count must be positive");
+ }
+ // Detect an excessive variadic buffer count to avoid potential memory
blowup
+ // (GH-48900).
+ const auto max_buffer_count =
+ static_cast<int64_t>(metadata_->buffers()->size()) - buffer_index_;
+ if (count > max_buffer_count) {
+ return Status::IOError("variadic buffer count exceeds available number
of buffers");
}
- return static_cast<size_t>(count);
+ return count;
}
Status GetFieldMetadata(int field_index, ArrayData* out) {
@@ -398,7 +404,7 @@ class ArrayLoader {
ARROW_ASSIGN_OR_RAISE(auto data_buffer_count,
GetVariadicCount(variadic_count_index_++));
out_->buffers.resize(data_buffer_count + 2);
- for (size_t i = 0; i < data_buffer_count; ++i) {
+ for (int64_t i = 0; i < data_buffer_count; ++i) {
RETURN_NOT_OK(GetBuffer(buffer_index_++, &out_->buffers[i + 2]));
}
return Status::OK();
diff --git a/testing b/testing
index 19dda67f48..7b641152dc 160000
--- a/testing
+++ b/testing
@@ -1 +1 @@
-Subproject commit 19dda67f485ffb3ffa92f4c6fa083576ef052d58
+Subproject commit 7b641152dcb0f9e197ebe24a1986151849250959