This is an automated email from the ASF dual-hosted git repository.
rok 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 a6c201816e GH-50054: [C++][IPC] Validate indices buffer size in
ReadSparseCOOIndex (#50055)
a6c201816e is described below
commit a6c201816e1a6dcd6dfa5d335a03afe5fb17423f
Author: metsw24-max <[email protected]>
AuthorDate: Tue Jun 30 18:28:26 2026 +0530
GH-50054: [C++][IPC] Validate indices buffer size in ReadSparseCOOIndex
(#50055)
### Rationale for this change
`ReadSparseCOOIndex` builds the indices `Tensor` of shape
`{non_zero_length, ndim}` over `indicesBuffer` with no size check, unlike the
sibling `ReadSparseCSXIndex`. A crafted COO message with a large
`non_zero_length` and a small buffer produces an index tensor that overruns its
buffer, giving an out-of-bounds read when the sparse tensor is consumed (for
example, converted to dense). A `non_zero_length` near `INT64_MAX` also
overflows the `non_zero_length * ndim * byte_width` size product.
### What changes are included in this PR?
A minimum-size guard on `indicesBuffer` in `ReadSparseCOOIndex`, mirroring
the existing check in `ReadSparseCSXIndex` and using `MultiplyWithOverflow` for
the size computation.
### Are these changes tested?
The guard is a no-op for the valid inputs covered by the round-trip tests
in `cpp/src/arrow/ipc/tensor_test.cc`; the rejection and overflow behaviour was
checked against a standalone reproducer of the size computation.
### Are there any user-facing changes?
Reading a malformed sparse COO tensor message now returns `Status::Invalid`
instead of constructing an out-of-bounds index tensor.
**This PR contains a "Critical Fix".** A malformed IPC SparseTensor (COO)
message could trigger an out-of-bounds read when the resulting sparse tensor is
consumed.
* GitHub Issue: #50054
Lead-authored-by: metsw24-max <[email protected]>
Co-authored-by: Rok Mihevc <[email protected]>
Signed-off-by: Rok Mihevc <[email protected]>
---
cpp/src/arrow/ipc/reader.cc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/cpp/src/arrow/ipc/reader.cc b/cpp/src/arrow/ipc/reader.cc
index b964c998dd..a7d24fa86c 100644
--- a/cpp/src/arrow/ipc/reader.cc
+++ b/cpp/src/arrow/ipc/reader.cc
@@ -2308,6 +2308,13 @@ Result<std::shared_ptr<SparseIndex>> ReadSparseCOOIndex(
file->ReadAt(indices_buffer->offset(),
indices_buffer->length(),
/*allow_short_read=*/false));
std::vector<int64_t> indices_shape({non_zero_length, ndim});
+ int64_t indices_minimum_bytes;
+ if (MultiplyWithOverflow(non_zero_length, ndim, &indices_minimum_bytes) ||
+ MultiplyWithOverflow(indices_minimum_bytes, indices_elsize,
+ &indices_minimum_bytes) ||
+ indices_minimum_bytes > indices_buffer->length()) {
+ return Status::Invalid("shape is inconsistent to the size of indices
buffer");
+ }
auto* indices_strides = sparse_index->indicesStrides();
std::vector<int64_t> strides(2);
if (indices_strides && indices_strides->size() > 0) {