Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

ArrowBuf.setBytes(long, ByteBuffer, int, int) does not bounds-check the source buffer

Open Beginner friendly
#1,336 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@aryan9948 is already working on this.

Since Oct 8, 2026.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
java
Domain
backend, security

Research direction

Start with ArrowBuf.setBytes(long, ByteBuffer, int, int) and compare its direct-buffer path with the sibling overloads that validate source bounds. Add a regression test using a direct source buffer whose requested range exceeds its capacity, then run the relevant ArrowBuf tests. Done when the invalid range is rejected and valid copies still pass.

Written by the indexing model from the issue text.

Description

Describe the bug, including details regarding any error messages, version, and platform.

ArrowBuf.setBytes(long index, ByteBuffer src, int srcIndex, int length) bound-checks only the
destination (checkIndex(index, length)), never srcIndex/length against src. On the direct
branch it takes the raw buffer address, adds srcIndex, and calls
MemoryUtil.copyMemory(srcAddress, dstAddress, length), so a request whose srcIndex + length
runs past src.capacity() reads off-heap memory beyond the source buffer and copies it into the
ArrowBuf.

The heap branch of the same method rejects the identical request (newBuf.limit(srcIndex + length)
throws), and the sibling overloads all do an unconditional isOutOfBounds check on the other
buffer: setBytes(long, byte[], int, long), setBytes(long, ArrowBuf, long, long),
getBytes(long, byte[], int, int), getBytes(long, ArrowBuf, long, int) and
NettyArrowBuf.setBytes(int, ByteBuf, int, int). This overload is the only one in the family
without one.

Reproducer (bounds checking left at its default, i.e. enabled — the missing check is on the source
side, so BoundsChecking does not cover it):

ByteBuffer backing = ByteBuffer.allocateDirect(32);
for (int i = 0; i < 32; i++) {
  backing.put(i, (byte) i);
}
ByteBuffer dup = backing.duplicate();
((Buffer) dup).position(0);
((Buffer) dup).limit(16);
ByteBuffer direct = dup.slice();          // isDirect=true, capacity=16

try (BufferAllocator allocator = new RootAllocator(128);
    ArrowBuf buf = allocator.buffer(16)) {
  buf.setBytes(0, direct, 8, 16);         // asks for src[8, 24) from a 16-byte source
  byte[] actual = new byte[16];
  buf.getBytes(0, actual);
  System.out.println(Arrays.toString(actual));
}

Output:

[8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]

The last eight bytes (16..23) are outside the source buffer. The same call with a heap
ByteBuffer raises IllegalArgumentException: newLimit > capacity: (24 > 16), and
buf.setBytes(0, new byte[16], 8, 16) raises IndexOutOfBoundsException.

This overload backs set/setSafe(int, ByteBuffer, int, int) on BaseVariableWidthVector,
BaseLargeVariableWidthVector, BaseVariableWidthViewVector and BaseFixedWidthVector, which
pass start/length straight through, so the adjacent memory lands in vector data that is then
returned to callers or written out over IPC.

Component(s)

Java

Dominant language
Java
Stars
98
Forks
160
Avg merge
5d 9h
Merged PRs (30d)
26

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from apache/arrow-java

All issues in apache/arrow-java

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.