Skip to content

GH-50161: [C++][IPC] Validate CSF sparse index buffer counts#50070

Merged
rok merged 3 commits into
apache:mainfrom
metsw24-max:ipc-csf-index-buffer-counts
Jun 30, 2026
Merged

GH-50161: [C++][IPC] Validate CSF sparse index buffer counts#50070
rok merged 3 commits into
apache:mainfrom
metsw24-max:ipc-csf-index-buffer-counts

Conversation

@metsw24-max

@metsw24-max metsw24-max commented May 31, 2026

Copy link
Copy Markdown
Contributor

Rationale for this change

ReadSparseCSFIndex in cpp/src/arrow/ipc/reader.cc sizes indptr_data/indices_data from the tensor shape (ndim - 1/ndim) but fills them by looping over the flatbuffer-supplied buffer counts, which are never checked against ndim. A crafted CSF sparse tensor message with mismatched counts writes past the end of those vectors, and ndim == 0 builds a SIZE_MAX-sized vector. The payload path is already guarded by CheckSparseTensorBodyBufferCount; the file/stream path was not, so this is reachable from ReadSparseTensor(io::InputStream*) on untrusted bytes. GetSparseCSFIndexMetadata in metadata_internal.cc has the same issue as an out-of-bounds read (axisOrder() vs indicesBuffers() lengths).

What changes are included in this PR?

Callee-side count validation in both functions: reject CSF indices whose indptrBuffers/indicesBuffers counts don't match ndim - 1/ndim (and ndim < 1), and whose axisOrder/indicesBuffers lengths differ, with Status::Invalid.

Are these changes tested?

Covered by the existing sparse tensor IPC round-trip tests; the rejected inputs are only producible from hand-crafted flatbuffers.

Are there any user-facing changes?

No, only invalid inputs are rejected.

This PR contains a "Critical Fix". A crafted IPC sparse tensor message could trigger a heap out-of-bounds write (shared_ptr<Buffer> constructions past the vector end) or an out-of-bounds flatbuffer read from the public ReadSparseTensor API.

@pitrou

pitrou commented Jun 10, 2026

Copy link
Copy Markdown
Member

@metsw24-max Bug fixes or security fixes are not minor changes, can you open a corresponding GH issue for this PR? Thank you!

@metsw24-max metsw24-max changed the title MINOR: [C++][IPC] Validate CSF sparse index buffer counts GH-50161: [C++][IPC] Validate CSF sparse index buffer counts Jun 12, 2026
@metsw24-max

Copy link
Copy Markdown
Contributor Author

Makes sense. Opened #50161 and retitled the PR, and filled in the template body since this qualifies as a critical fix.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #50161 has been automatically assigned in GitHub to PR creator.

@pitrou
pitrou requested a review from rok June 15, 2026 14:14

@rok rok left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. Could you please add some regression tests? I'm mostly interested in ndim=1 (it should be invalid CSF index if I remember correctly).

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Jun 15, 2026
@metsw24-max
metsw24-max requested a review from pitrou as a code owner June 16, 2026 05:46
@metsw24-max

Copy link
Copy Markdown
Contributor Author

Added regression tests in tensor_test.cc that feed hand-crafted CSF messages through ReadSparseTensor.

You're right about ndim=1: it has no indptr buffers, so it slipped past the old ndim < 1 guard and reached SparseCSFIndex's constructor, which dereferences indptr_.front() on an empty vector. I've tightened the reader to require ndim >= 2. The new test covers that case plus too-many indices buffers and an axisOrder/indicesBuffers length mismatch, and the existing round-trip tests still pass.

@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jun 16, 2026
@metsw24-max

Copy link
Copy Markdown
Contributor Author

Pushed a clang-format fix for the lint failure. The other two reds look unrelated to this change: the C++ AVX2 job fails on a Gandiva timezone test (TestTime.TestCastTimestampWithTZ) and the Windows Python job on a pyarrow flight import, neither of which this patch touches. The IPC tests built and passed on the ASAN/UBSAN and macOS C++ jobs.

@rok rok left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea to check.

@rok
rok merged commit e92d5d7 into apache:main Jun 30, 2026
55 checks passed
@rok rok removed the awaiting change review Awaiting change review label Jun 30, 2026
@github-actions github-actions Bot added the awaiting merge Awaiting merge label Jun 30, 2026
@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit e92d5d7.

There were 3 benchmark results indicating a performance regression:

The full Conbench report has more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants