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) {

Reply via email to