GH-50161: [C++][IPC] Validate CSF sparse index buffer counts#50070
Conversation
|
@metsw24-max Bug fixes or security fixes are not minor changes, can you open a corresponding GH issue for this PR? Thank you! |
|
Makes sense. Opened #50161 and retitled the PR, and filled in the template body since this qualifies as a critical fix. |
|
|
rok
left a comment
There was a problem hiding this comment.
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).
|
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 |
|
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. |
|
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. |
Rationale for this change
ReadSparseCSFIndexin cpp/src/arrow/ipc/reader.cc sizesindptr_data/indices_datafrom the tensor shape (ndim - 1/ndim) but fills them by looping over the flatbuffer-supplied buffer counts, which are never checked againstndim. A crafted CSF sparse tensor message with mismatched counts writes past the end of those vectors, andndim == 0builds aSIZE_MAX-sized vector. The payload path is already guarded byCheckSparseTensorBodyBufferCount; the file/stream path was not, so this is reachable fromReadSparseTensor(io::InputStream*)on untrusted bytes.GetSparseCSFIndexMetadatain metadata_internal.cc has the same issue as an out-of-bounds read (axisOrder()vsindicesBuffers()lengths).What changes are included in this PR?
Callee-side count validation in both functions: reject CSF indices whose
indptrBuffers/indicesBufferscounts don't matchndim - 1/ndim(andndim < 1), and whoseaxisOrder/indicesBufferslengths differ, withStatus::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 publicReadSparseTensorAPI.