Skip to content

GH-54570: [C++][Compute] Fix segfault casting null list with empty child to fixed_size_list - #54574

Open
ShivanshhhG wants to merge 1 commit into
apache:mainfrom
ShivanshhhG:fix-54570-cast-null-list-to-fixed-size-list
Open

ShivanshhhG wants to merge 1 commit into
apache:mainfrom
ShivanshhhG:fix-54570-cast-null-list-to-fixed-size-list

Conversation

@ShivanshhhG

Copy link
Copy Markdown

Rationale for this change

When casting a ListArray, LargeListArray, or ListViewArray to FixedSizeListArray, if the input array contains only null lists with an empty child array (which frequently occurs in IPC streams or deserialized batches from tools like Polars to_arrow()), cast_values->length is 0.

Previously, BuildTakeIndices populated index 0 for every null slot (builder.UnsafeAppend(0)). When Take was called with TakeOptions::NoBoundsCheck(), it attempted to access index 0 on an empty child array whose buffers may be null or unallocated, dereferencing a null pointer in FixedWidthTakeImpl and causing a segmentation fault (GH-54570).

What changes are included in this PR?

  1. If cast_values->length == 0, bypass Take entirely and directly create the output child array using MakeArrayOfNull(child_type, in_array.length * list_size, ctx->memory_pool()).
  2. In BuildTakeIndices, emit null indices (builder.UnsafeAppendNull()) for null list slots instead of index 0.
  3. Add regression tests in cpp/src/arrow/compute/kernels/scalar_cast_test.cc verifying that casting null lists with empty children (including unallocated child buffers) to FixedSizeList succeeds and produces the expected null list array.

Are these changes tested?

Yes, unit tests added to cpp/src/arrow/compute/kernels/scalar_cast_test.cc under TEST(Cast, ListToFSL).

Are there any user-facing changes?

No (fixes crash/segfault on valid spec-compliant input).

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #54570 has been automatically assigned in GitHub to PR creator.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #54570 has no components, please add labels for components.

auto child = ArrayFromJSON(int64(), "[]");
ASSERT_OK_AND_ASSIGN(
auto from,
ListArray::FromArrays(*ArrayFromJSON(int32(), "[0, 0]"), *child,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The C++ build has not run yet however compiling this locally reports an error because the third argument to FromArrays expects MemoryPool*, but receives an Array.

Did you compile/run this before submitting?

} else if (offsets[0] != 0) {
// No nulls, but we need to slice the values
cast_values = cast_values->Slice(offsets[0], in_array.length * list_size);
if (cast_values->length == 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list-view inputs mentioned in the description still fail before reaching this branch. ValidateLengths reads offsets[length], but list views have only length offsets and a separate sizes buffer.

Please add regression tests for all-null ListView and LargeListView inputs with empty children. Either handle these layouts here or narrow the claimed scope and track the remaining bug separately.

…pty child to fixed_size_list

When casting a ListArray or LargeListArray to FixedSizeListArray, if an array contains only null lists with an empty child array, cast_values->length is 0. Previously, BuildTakeIndices populated index 0 for null slots, and Take was called with TakeOptions::NoBoundsCheck(), dereferencing an unallocated child buffer and causing a segmentation fault.

This commit resolves the issue by:
1. Handling empty child values (cast_values->length == 0) directly using MakeArrayOfNull rather than attempting Take.
2. Emitting null indices (builder.UnsafeAppendNull()) for null list slots in BuildTakeIndices instead of index 0.
3. Adding regression tests for casting null lists with empty children and unallocated buffers to FixedSizeList.

Fixes: apache#54570

Signed-off-by: SHIVANSH-ux-ys <singaser78@gmail.com>
@ShivanshhhG
ShivanshhhG force-pushed the fix-54570-cast-null-list-to-fixed-size-list branch from b3807af to 1efe0d1 Compare October 26, 2026 12:13
@ShivanshhhG

Copy link
Copy Markdown
Author

Hi @dmitry-chirkov-dremio,

Thank you for the review! I have updated the PR to address both comments:

  1. FromArrays call argument order: Fixed the parameter order across all tests to supply MemoryPool* as the 3rd argument and the null validity bitmap buffer as the 4th argument.
  2. ListView / LargeListView support: Updated ValidateLengths using if constexpr (is_list_view_type<SrcType>::value) to read lengths from the sizes buffer (buffers[2]) and verify contiguous offsets rather than reading past the offsets buffer (offsets[length]). Added regression tests for all-null ListView and LargeListView inputs with empty children casting to FixedSizeList.

All tests and linters are updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants