Skip to content

fix: Return the schema when ArrowBasicArrayStreamInit() fails to allocate arrays - #1006

Open
pedrobtz wants to merge 1 commit into
apache:mainfrom
pedrobtz:fix-basic-array-stream-init-oom
Open

pedrobtz wants to merge 1 commit into
apache:mainfrom
pedrobtz:fix-basic-array-stream-init-oom

Conversation

@pedrobtz

@pedrobtz pedrobtz commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

When ArrowMalloc() fails for the arrays, ArrowBasicArrayStreamInit() calls ArrowBasicArrayStreamRelease(array_stream) before it has set any of array_stream's fields. The release callback then reads the caller's uninitialized release and private_data: if release happens to be non-NULL it dereferences an unset private_data, and if it is NULL nothing is released. Either way the schema, already moved into the private data, leaks.

The fix moves the schema back to the caller and frees the private data. That matches the first allocation failure, which returns ENOMEM before taking the schema. The documentation now says that the caller keeps the schema when the function fails.

The new ArrayStreamTestInitError test asks for INT64_MAX / sizeof(struct ArrowArray) arrays, so the second allocation fails. It expects ENOMEM, an untouched stream and a schema the caller still owns. Without the fix, the schema's release is NULL and the test fails. Like the other huge-allocation tests, it is skipped under __SANITIZE_ADDRESS__.

This came up while reviewing nanoarrow for the zuarrow R package, which vendors it.

ctest passes in a plain build and with ASan and UBSan (411 tests; the sanitizer run needs ASAN_OPTIONS=allocator_may_return_null=1 where the compiler does not define __SANITIZE_ADDRESS__, as for the existing huge-allocation tests). The changed files are formatted with the pinned clang-format 16.0.6.

🤖 Generated with Claude Code

…cate arrays

When ArrowMalloc() failed for the arrays, ArrowBasicArrayStreamInit()
called ArrowBasicArrayStreamRelease() on a stream whose private_data had
not been stored yet. The release callback then read the caller's unset
release and private_data fields, and the schema already moved into the
private data leaked. Move the schema back to the caller instead, as the
first allocation failure leaves it, and free the private data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@paleolimbot paleolimbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

This is a good catch, although it should probably just not touch the schema in the first place until the allocation has succeeded

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants