MINOR: Check source range in ArrowBuf.setBytes for direct ByteBuffers (#1380)

## What's Changed

`ArrowBuf.setBytes(long index, ByteBuffer src, int srcIndex, int
length)` bounds-checks only the destination. When `src` is a direct
buffer it copies `length` bytes from `getByteBufferAddress(src) +
srcIndex` with `MemoryUtil.copyMemory`, so a source range past
`src.capacity()` (or a negative `srcIndex`) silently copies adjacent
native memory into the ArrowBuf, even with bounds checking enabled. For
example, `buf.setBytes(0, ByteBuffer.allocateDirect(8), 0, 64)`
succeeds. The heap path already rejects this through
`ByteBuffer.position/limit`, and the `byte[]` and `ArrowBuf` overloads
(and `NettyArrowBuf.setBytes(ByteBuf)`) check the source with
`isOutOfBounds`. This adds the same source check before either path, so
the `set/setSafe(int, ByteBuffer, int, int)` methods on the
variable-width vectors fail with `IndexOutOfBoundsException` instead of
reading out of bounds. Valid ranges behave as before. Added a regression
test to `TestArrowBuf`.
diff --git a/memory/memory-core/src/main/java/org/apache/arrow/memory/ArrowBuf.java b/memory/memory-core/src/main/java/org/apache/arrow/memory/ArrowBuf.java
index c3eafaa..6bc113e 100644
--- a/memory/memory-core/src/main/java/org/apache/arrow/memory/ArrowBuf.java
+++ b/memory/memory-core/src/main/java/org/apache/arrow/memory/ArrowBuf.java
@@ -897,6 +897,12 @@
   public void setBytes(long index, ByteBuffer src, int srcIndex, int length) {
     // bound check for this ArrowBuf where the data will be copied into
     checkIndex(index, length);
+    // bound check for src ByteBuffer
+    if (isOutOfBounds(srcIndex, length, src.capacity())) {
+      throw new IndexOutOfBoundsException(
+          String.format(
+              "index: %d, length: %d (expected: range(0, %d))", srcIndex, length, src.capacity()));
+    }
     if (src.isDirect()) {
       // copy length bytes of data from src ByteBuffer starting at address
       // srcAddress into this ArrowBuf at address dstAddress
diff --git a/memory/memory-core/src/test/java/org/apache/arrow/memory/TestArrowBuf.java b/memory/memory-core/src/test/java/org/apache/arrow/memory/TestArrowBuf.java
index 60e118d..fdb7788 100644
--- a/memory/memory-core/src/test/java/org/apache/arrow/memory/TestArrowBuf.java
+++ b/memory/memory-core/src/test/java/org/apache/arrow/memory/TestArrowBuf.java
@@ -112,6 +112,17 @@
     }
   }
 
+  @Test
+  public void testSetBytesDirectOutOfBoundsSource_RaisesIndexOutOfBoundsException() {
+    ByteBuffer data = ByteBuffer.allocateDirect(8);
+    try (BufferAllocator allocator = new RootAllocator(128);
+        ArrowBuf buf = allocator.buffer(64)) {
+      assertThrows(IndexOutOfBoundsException.class, () -> buf.setBytes(0, data, 0, 64));
+      assertThrows(IndexOutOfBoundsException.class, () -> buf.setBytes(0, data, 4, 8));
+      assertThrows(IndexOutOfBoundsException.class, () -> buf.setBytes(0, data, -1, 4));
+    }
+  }
+
   /** ARROW-9221: guard against big-endian byte buffers. */
   @Test
   public void testSetBytesBigEndian() {