From 4e4d7124aef98fff17c4a3f3f4a15b12893ba1c8 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Sat, 12 Sep 2026 00:13:07 +0200 Subject: [PATCH] fix: allow null data for empty binary and string views Signed-off-by: Fredrik Fornwall --- src/nanoarrow/common/array_test.cc | 24 ++++++++++++++++++++++++ src/nanoarrow/common/inline_array.h | 4 +++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/nanoarrow/common/array_test.cc b/src/nanoarrow/common/array_test.cc index 4bb3cd95b..1b0d1290c 100644 --- a/src/nanoarrow/common/array_test.cc +++ b/src/nanoarrow/common/array_test.cc @@ -1193,6 +1193,30 @@ TEST(ArrayTest, ArrayTestAppendToStringViewArray) { }); }; +TEST(ArrayTest, ArrayTestAppendNullDataToViewArray) { + for (enum ArrowType arrow_type : + {NANOARROW_TYPE_BINARY_VIEW, NANOARROW_TYPE_STRING_VIEW}) { + SCOPED_TRACE(ArrowTypeString(arrow_type)); + nanoarrow::UniqueArray array; + ASSERT_EQ(ArrowArrayInitFromType(array.get(), arrow_type), NANOARROW_OK); + ASSERT_EQ(ArrowArrayStartAppending(array.get()), NANOARROW_OK); + + // Empty buffer and string views may have a null data pointer. + // Run with UBSan to detect passing these pointers to memcpy, even with size 0. + ASSERT_EQ(ArrowArrayAppendBytes(array.get(), {{nullptr}, 0}), NANOARROW_OK); + ASSERT_EQ(ArrowArrayAppendString(array.get(), ArrowCharView(nullptr)), NANOARROW_OK); + ASSERT_EQ(ArrowArrayFinishBuildingDefault(array.get(), nullptr), NANOARROW_OK); + + EXPECT_EQ(array->length, 2); + EXPECT_EQ(array->null_count, 0); + auto inline_buffer = + reinterpret_cast(array->buffers[1]); + for (int64_t i = 0; i < array->length; i++) { + EXPECT_EQ(inline_buffer[i].inlined.size, 0); + } + } +} + TEST(ArrayTest, ArrayTestAppendToFixedSizeBinaryArray) { struct ArrowArray array; struct ArrowSchema schema; diff --git a/src/nanoarrow/common/inline_array.h b/src/nanoarrow/common/inline_array.h index 885276b49..9bfc6dbda 100644 --- a/src/nanoarrow/common/inline_array.h +++ b/src/nanoarrow/common/inline_array.h @@ -589,7 +589,9 @@ static inline ArrowErrorCode ArrowArrayAppendBytes(struct ArrowArray* array, bvt.inlined.size = (int32_t)value.size_bytes; if (value.size_bytes <= NANOARROW_BINARY_VIEW_INLINE_SIZE) { - memcpy(bvt.inlined.data, value.data.as_char, value.size_bytes); + if (value.size_bytes > 0) { + memcpy(bvt.inlined.data, value.data.as_char, value.size_bytes); + } memset(bvt.inlined.data + bvt.inlined.size, 0, NANOARROW_BINARY_VIEW_INLINE_SIZE - bvt.inlined.size); } else {