Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions src/nanoarrow/common/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -1820,14 +1820,16 @@ static int ArrowArrayViewValidateDefault(struct ArrowArrayView* array_view,
case NANOARROW_TYPE_STRING:
case NANOARROW_TYPE_BINARY:
if (array_view->buffer_views[1].size_bytes != 0) {
first_offset = array_view->buffer_views[1].data.as_int32[array_view->offset];
first_offset = ArrowBufferViewGetInt32Unsafe(&array_view->buffer_views[1],
array_view->offset);
if (first_offset < 0) {
ArrowErrorSet(error, "Expected first offset >= 0 but found %" PRId64,
first_offset);
return EINVAL;
}

last_offset = array_view->buffer_views[1].data.as_int32[offset_plus_length];
last_offset = ArrowBufferViewGetInt32Unsafe(&array_view->buffer_views[1],
offset_plus_length);
if (last_offset < 0) {
ArrowErrorSet(error, "Expected last offset >= 0 but found %" PRId64,
last_offset);
Expand Down Expand Up @@ -1856,14 +1858,16 @@ static int ArrowArrayViewValidateDefault(struct ArrowArrayView* array_view,
case NANOARROW_TYPE_LARGE_STRING:
case NANOARROW_TYPE_LARGE_BINARY:
if (array_view->buffer_views[1].size_bytes != 0) {
first_offset = array_view->buffer_views[1].data.as_int64[array_view->offset];
first_offset = ArrowBufferViewGetInt64Unsafe(&array_view->buffer_views[1],
array_view->offset);
if (first_offset < 0) {
ArrowErrorSet(error, "Expected first offset >= 0 but found %" PRId64,
first_offset);
return EINVAL;
}

last_offset = array_view->buffer_views[1].data.as_int64[offset_plus_length];
last_offset = ArrowBufferViewGetInt64Unsafe(&array_view->buffer_views[1],
offset_plus_length);
if (last_offset < 0) {
ArrowErrorSet(error, "Expected last offset >= 0 but found %" PRId64,
last_offset);
Expand Down Expand Up @@ -1905,14 +1909,16 @@ static int ArrowArrayViewValidateDefault(struct ArrowArrayView* array_view,
case NANOARROW_TYPE_LIST:
case NANOARROW_TYPE_MAP:
if (array_view->buffer_views[1].size_bytes != 0) {
first_offset = array_view->buffer_views[1].data.as_int32[array_view->offset];
first_offset = ArrowBufferViewGetInt32Unsafe(&array_view->buffer_views[1],
array_view->offset);
if (first_offset < 0) {
ArrowErrorSet(error, "Expected first offset >= 0 but found %" PRId64,
first_offset);
return EINVAL;
}

last_offset = array_view->buffer_views[1].data.as_int32[offset_plus_length];
last_offset = ArrowBufferViewGetInt32Unsafe(&array_view->buffer_views[1],
offset_plus_length);
if (last_offset < 0) {
ArrowErrorSet(error, "Expected last offset >= 0 but found %" PRId64,
last_offset);
Expand All @@ -1933,14 +1939,16 @@ static int ArrowArrayViewValidateDefault(struct ArrowArrayView* array_view,

case NANOARROW_TYPE_LARGE_LIST:
if (array_view->buffer_views[1].size_bytes != 0) {
first_offset = array_view->buffer_views[1].data.as_int64[array_view->offset];
first_offset = ArrowBufferViewGetInt64Unsafe(&array_view->buffer_views[1],
array_view->offset);
if (first_offset < 0) {
ArrowErrorSet(error, "Expected first offset >= 0 but found %" PRId64,
first_offset);
return EINVAL;
}

last_offset = array_view->buffer_views[1].data.as_int64[offset_plus_length];
last_offset = ArrowBufferViewGetInt64Unsafe(&array_view->buffer_views[1],
offset_plus_length);
if (last_offset < 0) {
ArrowErrorSet(error, "Expected last offset >= 0 but found %" PRId64,
last_offset);
Expand Down Expand Up @@ -2037,7 +2045,8 @@ static int ArrowAssertIncreasingInt32(struct ArrowBufferView view,
}

for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int32_t); i++) {
if (view.data.as_int32[i] < view.data.as_int32[i - 1]) {
if (ArrowBufferViewGetInt32Unsafe(&view, i) <
ArrowBufferViewGetInt32Unsafe(&view, i - 1)) {
ArrowErrorSet(error, "[%" PRId64 "] Expected element size >= 0", i);
return EINVAL;
}
Expand All @@ -2053,7 +2062,8 @@ static int ArrowAssertIncreasingInt64(struct ArrowBufferView view,
}

for (int64_t i = 1; i < view.size_bytes / (int64_t)sizeof(int64_t); i++) {
if (view.data.as_int64[i] < view.data.as_int64[i - 1]) {
if (ArrowBufferViewGetInt64Unsafe(&view, i) <
ArrowBufferViewGetInt64Unsafe(&view, i - 1)) {
ArrowErrorSet(error, "[%" PRId64 "] Expected element size >= 0", i);
return EINVAL;
}
Expand Down Expand Up @@ -2110,14 +2120,14 @@ static int ArrowArrayViewValidateFull(struct ArrowArrayView* array_view,
}
if (array_view->layout.element_size_bits[i] == 32) {
struct ArrowBufferView sliced_offsets;
sliced_offsets.data.as_int32 =
array_view->buffer_views[i].data.as_int32 + array_view->offset;
sliced_offsets.data.as_uint8 = array_view->buffer_views[i].data.as_uint8 +
array_view->offset * sizeof(int32_t);
sliced_offsets.size_bytes = (array_view->length + 1) * sizeof(int32_t);
NANOARROW_RETURN_NOT_OK(ArrowAssertIncreasingInt32(sliced_offsets, error));
} else {
struct ArrowBufferView sliced_offsets;
sliced_offsets.data.as_int64 =
array_view->buffer_views[i].data.as_int64 + array_view->offset;
sliced_offsets.data.as_uint8 = array_view->buffer_views[i].data.as_uint8 +
array_view->offset * sizeof(int64_t);
sliced_offsets.size_bytes = (array_view->length + 1) * sizeof(int64_t);
NANOARROW_RETURN_NOT_OK(ArrowAssertIncreasingInt64(sliced_offsets, error));
}
Expand Down
42 changes: 42 additions & 0 deletions src/nanoarrow/common/array_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2907,6 +2907,48 @@ TEST(ArrayTest, ArrayViewTestString) {
ArrowArrayViewReset(&array_view);
}

TEST(ArrayTest, ArrayViewTestValidateUnalignedOffsets) {
struct ArrowError error;

{
struct ArrowArrayView array_view;
uint8_t offsets[1 + 3 * sizeof(int32_t)] = {};
const int32_t expected[] = {0, 1, 3};
memcpy(offsets + 1, expected, sizeof(expected));

ArrowArrayViewInitFromType(&array_view, NANOARROW_TYPE_STRING);
ArrowArrayViewSetLength(&array_view, 2);
array_view.buffer_views[1].data.as_uint8 = offsets + 1;
array_view.buffer_views[1].size_bytes = sizeof(expected);
array_view.buffer_views[2].data.as_uint8 = offsets;
array_view.buffer_views[2].size_bytes = 3;

EXPECT_EQ(
ArrowArrayViewValidate(&array_view, NANOARROW_VALIDATION_LEVEL_FULL, &error),
NANOARROW_OK);
ArrowArrayViewReset(&array_view);
}

{
struct ArrowArrayView array_view;
uint8_t offsets[1 + 3 * sizeof(int64_t)] = {};
const int64_t expected[] = {0, 1, 3};
memcpy(offsets + 1, expected, sizeof(expected));

ArrowArrayViewInitFromType(&array_view, NANOARROW_TYPE_LARGE_STRING);
ArrowArrayViewSetLength(&array_view, 2);
array_view.buffer_views[1].data.as_uint8 = offsets + 1;
array_view.buffer_views[1].size_bytes = sizeof(expected);
array_view.buffer_views[2].data.as_uint8 = offsets;
array_view.buffer_views[2].size_bytes = 3;

EXPECT_EQ(
ArrowArrayViewValidate(&array_view, NANOARROW_VALIDATION_LEVEL_FULL, &error),
NANOARROW_OK);
ArrowArrayViewReset(&array_view);
}
}

TEST(ArrayTest, ArrayViewTestLargeString) {
struct ArrowArrayView array_view;
struct ArrowError error;
Expand Down
14 changes: 14 additions & 0 deletions src/nanoarrow/common/inline_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,20 @@ struct ArrowBufferView {
int64_t size_bytes;
};

static inline int32_t ArrowBufferViewGetInt32Unsafe(const struct ArrowBufferView* view,
int64_t i) {
int32_t value;
memcpy(&value, view->data.as_uint8 + i * sizeof(int32_t), sizeof(value));
return value;
}

static inline int64_t ArrowBufferViewGetInt64Unsafe(const struct ArrowBufferView* view,
int64_t i) {
int64_t value;
memcpy(&value, view->data.as_uint8 + i * sizeof(int64_t), sizeof(value));
return value;
}

/// \brief Array buffer allocation and deallocation
/// \ingroup nanoarrow-buffer
///
Expand Down
Loading