This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 8126a1bb fix(memory): handle zero-length checked reallocations (#1132)
8126a1bb is described below
commit 8126a1bbfdcff297488a43cc69f2edc4f47f2c23
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 12 19:51:55 2026 +0200
fix(memory): handle zero-length checked reallocations (#1132)
### Rationale for this change
CheckedAllocator.Reallocate panics when called with nil, and zero-size
reallocations leave stale entries in the leak-tracking map.
### What changes are included in this PR?
Handle nil input buffers and remove the old allocation record when a
reallocation reduces the size to zero. Add coverage for both paths.
### Are these changes tested?
- `go test ./arrow/memory`
### Are there any user-facing changes?
CheckedAllocator no longer panics or reports a false allocation leak for
these reallocation paths. The allocator interface is unchanged.
---
arrow/memory/buffer_test.go | 11 +++++++++++
arrow/memory/checked_allocator.go | 9 +++++++--
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/arrow/memory/buffer_test.go b/arrow/memory/buffer_test.go
index 549d57c4..7b413ec1 100644
--- a/arrow/memory/buffer_test.go
+++ b/arrow/memory/buffer_test.go
@@ -58,6 +58,17 @@ func TestNewResizableBuffer(t *testing.T) {
assert.Zero(t, buf.Len())
}
+func TestCheckedAllocatorReallocate(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ buf := mem.Reallocate(16, nil)
+ assert.Len(t, buf, 16)
+
+ buf = mem.Reallocate(0, buf)
+ assert.Empty(t, buf)
+}
+
func TestBufferReset(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
diff --git a/arrow/memory/checked_allocator.go
b/arrow/memory/checked_allocator.go
index 2c3726d2..95ac8d5e 100644
--- a/arrow/memory/checked_allocator.go
+++ b/arrow/memory/checked_allocator.go
@@ -68,14 +68,19 @@ func (a *CheckedAllocator) Allocate(size int) []byte {
func (a *CheckedAllocator) Reallocate(size int, b []byte) []byte {
a.sz.Add(int64(size - len(b)))
- oldptr := uintptr(unsafe.Pointer(&b[0]))
+ var oldptr uintptr
+ if len(b) > 0 {
+ oldptr = uintptr(unsafe.Pointer(unsafe.SliceData(b)))
+ }
out := a.mem.Reallocate(size, b)
+ if oldptr != 0 {
+ a.allocs.Delete(oldptr)
+ }
if size == 0 {
return out
}
newptr := uintptr(unsafe.Pointer(&out[0]))
- a.allocs.Delete(oldptr)
pcs := make([]uintptr, maxRetainedFrames)
// For historical reasons the meaning of the skip argument