From 85256aff75f29c739c198ea150f391a6e3fd35d9 Mon Sep 17 00:00:00 2001 From: Nayana Naik Date: Tue, 27 Oct 2026 13:55:25 +0530 Subject: [PATCH] Check for empty index batch in dictionary DecodeArrow --- cpp/src/parquet/decoder.cc | 3 +++ cpp/src/parquet/encoding_test.cc | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/cpp/src/parquet/decoder.cc b/cpp/src/parquet/decoder.cc index f90b56a7321..de628ce94b1 100644 --- a/cpp/src/parquet/decoder.cc +++ b/cpp/src/parquet/decoder.cc @@ -1392,6 +1392,9 @@ class DictByteArrayDecoderImpl : public DictDecoderImpl { int32_t batch_size = std::min(kBufferSize, num_values - num_appended - null_count); int num_indices = idx_decoder_.GetBatch(indices, batch_size); + if (ARROW_PREDICT_FALSE(num_indices < 1)) { + return Status::Invalid("Invalid number of indices: ", num_indices); + } int i = 0; while (true) { diff --git a/cpp/src/parquet/encoding_test.cc b/cpp/src/parquet/encoding_test.cc index 142dcbbf106..eb0a2e0c0ba 100644 --- a/cpp/src/parquet/encoding_test.cc +++ b/cpp/src/parquet/encoding_test.cc @@ -1373,6 +1373,22 @@ TEST_F(DictEncoding, CheckDecodeArrowNonNullDictBuilder) { this->CheckDecodeArrowNonNullUsingDictBuilder(); } +TEST_F(DictEncoding, CheckDecodeArrowDictBuilderTruncatedIndices) { + // The index stream ends before num_values - null_count indices have been + // decoded, so a refill of the index buffer returns no indices at all + InitTestCase(::arrow::binary(), /*null_probability=*/0.5, /*create_dict=*/true); + dict_decoder_->SetData(num_values_, buffer_->data(), + static_cast(buffer_->size()) / 2); + auto builder = CreateDictBuilder(); + EXPECT_THROW_THAT( + [&]() { + decoder_->DecodeArrow(num_values_, null_count_, valid_bits_, 0, builder.get()); + }, + ParquetException, + ::testing::Property(&ParquetException::what, + ::testing::HasSubstr("Invalid number of indices"))); +} + TEST_F(DictEncoding, CheckDecodeIndicesSpaced) { for (auto np : null_probabilities_) { InitTestCase(::arrow::binary(), np, /*create_dict=*/true);