Skip to content

fix: release temporary cast arrays after ownership transfer#898

Open
fallintoplace wants to merge 3 commits into
apache:mainfrom
fallintoplace:fix-cast-binary-temp-release
Open

fix: release temporary cast arrays after ownership transfer#898
fallintoplace wants to merge 3 commits into
apache:mainfrom
fallintoplace:fix-cast-binary-temp-release

Conversation

@fallintoplace

@fallintoplace fallintoplace commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Problem

CastBinaryToBinaryView and CastBinaryViewToBinary each create a temporary result array with ba.bldr.NewArray(), transfer ownership of its buffers with out.TakeOwnership(result.Data()), and then return without releasing the temporary array. TakeOwnership only transfers buffer ownership, so the temporary array retains its own reference and can leak memory per cast.

Change

  • Add defer result.Release() after creating the temporary result array in:
    • CastBinaryToBinaryView
    • CastBinaryViewToBinary
  • Keep the existing TakeOwnership behavior intact.

Impact

  • Prevents temporary-array retention/leakage in both cast paths.
  • No behavior change for successful casts besides corrected memory ownership semantics.

Testing

  • Added regression tests in arrow/compute/cast_test.go:
    • TestBinaryToBinaryViewReleasesTemporaryResult
    • TestBinaryViewToBinaryReleasesTemporaryResult
  • Each test verifies allocator balance with memory.NewCheckedAllocatorScope after releasing cast outputs and inputs.

@fallintoplace fallintoplace requested a review from zeroshade as a code owner July 4, 2026 01:06

@zeroshade zeroshade 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.

The production fix is correct and worth having — ArraySpan.TakeOwnership retains the buffers (arrow/compute/exec/span.go), so the ba.bldr.NewArray() temporary was leaking without the defer result.Release().

But both new tests fail:

cast_test.go:1682: invalid memory size exp=192, got=0
cast_test.go:1694: invalid memory size exp=32896, got=0
--- FAIL: TestCasts/TestBinaryToBinaryViewReleasesTemporaryResult
--- FAIL: TestCasts/TestBinaryViewToBinaryReleasesTemporaryResult

The scope is created after in is allocated, but the test releases in inside the scope before CheckSize, so outstanding drops below the baseline (exp = size of in, got = 0). Either call scope.CheckSize(c.T()) before in.Release(), or allocate in inside the scope. Once the harness is fixed these will lock the fix in nicely. Verified against the PR head with go test.

@zeroshade

Copy link
Copy Markdown
Member

@fallintoplace nudge — the fix itself is correct (TakeOwnership retains, so releasing the temporary is right). The two new tests just need scope.CheckSize(c.T()) called before in.Release() (or allocate in inside the scope) — as written they drop below the baseline and fail. Ping me for a re-review.

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