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

paleolimbot 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 b896d19e fix: allow null data for empty binary and string views during 
append (#940)
b896d19e is described below

commit b896d19e4afc0b519bec808003257cf24bf3ebe9
Author: Fredrik Fornwall <[email protected]>
AuthorDate: Sat Sep 12 04:57:10 2026 +0200

    fix: allow null data for empty binary and string views during append (#940)
    
    
[ArrowBufferView](https://arrow.apache.org/nanoarrow/latest/reference/c.html#_CPPv4N15ArrowBufferView4dataE)
    and
    
[ArrowStringView](https://arrow.apache.org/nanoarrow/latest/reference/c.html#_CPPv4N15ArrowStringView4dataE)
    allow a null data pointer when their size is zero:
    
    > If size_bytes is 0, this value may be NULL.
    
    Appending these views to binary-view or string-view arrays currently
    passes the null pointer to `memcpy`, which is undefined behaviour even
    for a zero-byte copy as flagged by UBSan.
    
    Skip the inline copy for empty values to fix that.
    
    Signed-off-by: Fredrik Fornwall <[email protected]>
---
 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 4bb3cd95..1b0d1290 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<const union ArrowBinaryView*>(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 885276b4..9bfc6dbd 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 {

Reply via email to