This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 221124a58 GH-238: Stop TestEmptyArrowBuf writing past the end of a 
native allocation (#1426)
221124a58 is described below

commit 221124a58a6739c8911116d3e21cc5758c14f761
Author: Andy Grove <[email protected]>
AuthorDate: Sat Oct 31 23:33:22 2026 -0600

    GH-238: Stop TestEmptyArrowBuf writing past the end of a native allocation 
(#1426)
    
    ## What's Changed
    
    `TestEmptyArrowBuf.testEmptyArrowBuf` wrapped the address of Netty's
    empty buffer, an 8-byte native allocation, in a 1024-byte `ArrowBuf` and
    wrote 10 bytes through it. The test now backs the no-op buffer with 1024
    bytes from its own allocator, so it writes only memory it owns. The
    assertions are unchanged.
    
    This overrun causes the intermittent "Error occurred in starting fork"
    failure of `arrow-memory-netty` in the Windows CI job. #238 has the
    analysis.
    
    Before this change, `testEmptyArrowBuf` fails on macOS when a `malloc`
    interposer ends 8-byte allocations at a guard page. With it, the whole
    `memory-netty` suite passes under the same interposer and normally. One
    green Windows run would not prove much, because the failure hit about 7%
    of runs.
    
    Closes #238.
---
 .../arrow/memory/netty/TestEmptyArrowBuf.java      | 60 +++++++++++-----------
 1 file changed, 29 insertions(+), 31 deletions(-)

diff --git 
a/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestEmptyArrowBuf.java
 
b/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestEmptyArrowBuf.java
index 3ce0705b4..642619324 100644
--- 
a/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestEmptyArrowBuf.java
+++ 
b/memory/memory-netty/src/test/java/org/apache/arrow/memory/netty/TestEmptyArrowBuf.java
@@ -19,7 +19,6 @@ package org.apache.arrow.memory.netty;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 
-import io.netty.buffer.PooledByteBufAllocatorL;
 import org.apache.arrow.memory.ArrowBuf;
 import org.apache.arrow.memory.ReferenceManager;
 import org.apache.arrow.memory.RootAllocator;
@@ -57,39 +56,38 @@ public class TestEmptyArrowBuf {
 
   @Test
   public void testEmptyArrowBuf() {
-    ArrowBuf buf =
-        new ArrowBuf(
-            ReferenceManager.NO_OP,
-            null,
-            1024,
-            new PooledByteBufAllocatorL().empty.memoryAddress());
+    // Back the buffer with real memory of the declared capacity. The writes 
below would otherwise
+    // run past the end of the native allocation and could corrupt the native 
heap.
+    try (ArrowBuf memory = allocator.buffer(1024)) {
+      ArrowBuf buf = new ArrowBuf(ReferenceManager.NO_OP, null, 1024, 
memory.memoryAddress());
 
-    buf.getReferenceManager().retain();
-    buf.getReferenceManager().retain(8);
-    assertEquals(1024, buf.capacity());
-    assertEquals(1, buf.getReferenceManager().getRefCount());
-    assertEquals(0, buf.getActualMemoryConsumed());
+      buf.getReferenceManager().retain();
+      buf.getReferenceManager().retain(8);
+      assertEquals(1024, buf.capacity());
+      assertEquals(1, buf.getReferenceManager().getRefCount());
+      assertEquals(0, buf.getActualMemoryConsumed());
 
-    for (int i = 0; i < 10; i++) {
-      buf.setByte(i, i);
-    }
-    assertEquals(0, buf.getActualMemoryConsumed());
-    assertEquals(0, buf.getReferenceManager().getSize());
-    assertEquals(0, buf.getReferenceManager().getAccountedSize());
-    assertFalse(buf.getReferenceManager().release());
-    assertFalse(buf.getReferenceManager().release(2));
-    assertEquals(0, buf.getReferenceManager().getAllocator().getLimit());
-    assertEquals(
-        buf, buf.getReferenceManager().transferOwnership(buf, 
allocator).getTransferredBuffer());
-    assertEquals(0, buf.readerIndex());
-    assertEquals(0, buf.writerIndex());
-    assertEquals(1, buf.refCnt());
+      for (int i = 0; i < 10; i++) {
+        buf.setByte(i, i);
+      }
+      assertEquals(0, buf.getActualMemoryConsumed());
+      assertEquals(0, buf.getReferenceManager().getSize());
+      assertEquals(0, buf.getReferenceManager().getAccountedSize());
+      assertFalse(buf.getReferenceManager().release());
+      assertFalse(buf.getReferenceManager().release(2));
+      assertEquals(0, buf.getReferenceManager().getAllocator().getLimit());
+      assertEquals(
+          buf, buf.getReferenceManager().transferOwnership(buf, 
allocator).getTransferredBuffer());
+      assertEquals(0, buf.readerIndex());
+      assertEquals(0, buf.writerIndex());
+      assertEquals(1, buf.refCnt());
 
-    ArrowBuf derive = buf.getReferenceManager().deriveBuffer(buf, 0, 100);
-    assertEquals(derive, buf);
-    assertEquals(1, buf.refCnt());
-    assertEquals(1, derive.refCnt());
+      ArrowBuf derive = buf.getReferenceManager().deriveBuffer(buf, 0, 100);
+      assertEquals(derive, buf);
+      assertEquals(1, buf.refCnt());
+      assertEquals(1, derive.refCnt());
 
-    buf.close();
+      buf.close();
+    }
   }
 }

Reply via email to