This is an automated email from the ASF dual-hosted git repository.

ianmcook pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-nanoarrow.git


The following commit(s) were added to refs/heads/main by this push:
     new bb5d8d70 fix(ipc): Decode a DictionaryEncoding without indexType as 
int32 indices (#957)
bb5d8d70 is described below

commit bb5d8d700b57fe99b8fdadf2babe680a3de60673
Author: Animesh Kumar <[email protected]>
AuthorDate: Fri Oct 9 08:47:23 2026 +0530

    fix(ipc): Decode a DictionaryEncoding without indexType as int32 indices 
(#957)
    
    Closes #956
    
    `Schema.fbs` says that when `DictionaryEncoding.indexType` is null, the
    indices must be signed int32. The decoder passed the missing table
    straight to `ArrowIpcDecoderSetTypeInt()`, which crashed (a segfault in
    release builds, flatcc's "null pointer table access" assertion in debug
    builds). It now uses int32 when the field isn't present.
    
    The new `NanoarrowIpcDecodeDictionarySchemaWithoutIndexType` test
    decodes a schema message with one `dictionary<values=string,
    indices=int32>` field that pyarrow 25.0.1 wrote, with `indexType` then
    removed from it. It crashes without the fix. I also read the
    `WITHOUT_INDEX_TYPE` stream from the issue with
    `ArrowIpcArrayStreamReader`: it now gives `struct<text:
    dictionary(int32)<string>>` with the values `a b a`, the same as the
    stream that has `indexType`.
    
    `ctest` passes (384 tests, compression tests skipped), and pre-commit
    passes on the changed files.
---
 src/nanoarrow/ipc/decoder.c       | 10 +++++++--
 src/nanoarrow/ipc/decoder_test.cc | 44 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/src/nanoarrow/ipc/decoder.c b/src/nanoarrow/ipc/decoder.c
index 9826b759..8eb91fe5 100644
--- a/src/nanoarrow/ipc/decoder.c
+++ b/src/nanoarrow/ipc/decoder.c
@@ -1246,8 +1246,14 @@ static int ArrowIpcSetDictionaryEncoding(
                                      error);
   NANOARROW_RETURN_NOT_OK_WITH_ERROR(ArrowSchemaSetName(schema->dictionary, 
""), error);
 
-  NANOARROW_RETURN_NOT_OK(ArrowIpcDecoderSetTypeInt(
-      schema, ns(DictionaryEncoding_indexType_get(dictionary_encoding)), 
error));
+  // Schema.fbs: "If this field is null, the indices must be signed int32."
+  if (ns(DictionaryEncoding_indexType_is_present(dictionary_encoding))) {
+    NANOARROW_RETURN_NOT_OK(ArrowIpcDecoderSetTypeInt(
+        schema, ns(DictionaryEncoding_indexType_get(dictionary_encoding)), 
error));
+  } else {
+    NANOARROW_RETURN_NOT_OK(
+        ArrowIpcDecoderSetTypeSimple(schema, NANOARROW_TYPE_INT32, error));
+  }
 
   if (ns(DictionaryEncoding_isOrdered_get(dictionary_encoding))) {
     schema->flags |= ARROW_FLAG_DICTIONARY_ORDERED;
diff --git a/src/nanoarrow/ipc/decoder_test.cc 
b/src/nanoarrow/ipc/decoder_test.cc
index dcdde176..b2cbaf7d 100644
--- a/src/nanoarrow/ipc/decoder_test.cc
+++ b/src/nanoarrow/ipc/decoder_test.cc
@@ -195,6 +195,23 @@ alignas(8) static uint8_t kDictionarySchema[] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 
0x04, 0x00,
     0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
+// Schema message with one field, some_col: dictionary<values=string, 
indices=int32>,
+// written by pyarrow 25.0.1 with DictionaryEncoding.indexType removed (null 
means
+// signed int32 per Schema.fbs)
+alignas(8) static uint8_t kDictionarySchemaNoIndexType[] = {
+    0xff, 0xff, 0xff, 0xff, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
0x00, 0x00,
+    0x0a, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0a, 0x00, 
0x00, 0x00,
+    0x00, 0x01, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 
0x04, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 
0x18, 0x00,
+    0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 
0x10, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 
0x00, 0x00,
+    0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x08, 0x00,
+    0x00, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x00, 0x00, 
0x00, 0x00,
+    0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0xd8, 0xff, 0xff, 0xff, 
0x0c, 0x00,
+    0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 
0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 
0x04, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 
0x00, 0x00};
+
 alignas(8) static uint8_t kDictionaryBatch[] = {
     0xff, 0xff, 0xff, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 
0x00, 0x00,
     0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x06, 0x00, 0x05, 0x00, 0x08, 0x00, 
0x0c, 0x00,
@@ -664,6 +681,33 @@ TEST(NanoarrowIpcTest, NanoarrowIpcDecodeDictionarySchema) 
{
   ArrowIpcDecoderReset(&decoder);
 }
 
+TEST(NanoarrowIpcTest, NanoarrowIpcDecodeDictionarySchemaWithoutIndexType) {
+  struct ArrowIpcDecoder decoder;
+  struct ArrowError error;
+  struct ArrowSchema schema;
+
+  struct ArrowBufferView data;
+  data.data.as_uint8 = kDictionarySchemaNoIndexType;
+  data.size_bytes = sizeof(kDictionarySchemaNoIndexType);
+
+  ASSERT_EQ(ArrowIpcDecoderInit(&decoder), NANOARROW_OK);
+
+  ASSERT_EQ(ArrowIpcDecoderDecodeHeader(&decoder, data, &error), NANOARROW_OK)
+      << error.message;
+  ASSERT_EQ(decoder.message_type, NANOARROW_IPC_MESSAGE_TYPE_SCHEMA);
+
+  ASSERT_EQ(ArrowIpcDecoderDecodeSchema(&decoder, &schema, &error), 
NANOARROW_OK)
+      << error.message;
+  ASSERT_EQ(schema.n_children, 1);
+  EXPECT_STREQ(schema.children[0]->name, "some_col");
+  EXPECT_STREQ(schema.children[0]->format, "i");
+  ASSERT_NE(schema.children[0]->dictionary, nullptr);
+  EXPECT_STREQ(schema.children[0]->dictionary->format, "u");
+
+  ArrowSchemaRelease(&schema);
+  ArrowIpcDecoderReset(&decoder);
+}
+
 TEST(NanoarrowIpcTest, NanoarrowIpcDictionaryEncodingsUniqueIds) {
   // Create dictionary encodings there is at least one duplicated identifier
   struct ArrowIpcDictionaryEncodings dictionary_encodings;

Reply via email to