ArrowBuf.setBytes(long, ByteBuffer, int, int) does not bounds-check the source buffer
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
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
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apache/arrow-java
-
Flight SQL JDBC parses boolean properties case-sensitively, silently disabling TLS for useEncryption=TRUEPossibly taken @Arawoof06 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
apache/arrow-java#1357 ·
Maintainers usually reply within 1 day
-
ArrowFlightJdbcArray.getArray(index, count) can read past the end of the array slicePossibly taken @Arawoof06 claimed this 85 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apache/arrow-java#1236 ·
Maintainers usually reply within 1 day
-
[Java][JDBC] ClobConsumer writes past VarCharVector data buffer for large CLOBsPossibly taken @Arawoof06 claimed this 90 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apache/arrow-java#1230 ·
Maintainers usually reply within 1 day
-
[Java] DictionaryEncoder doesn't crash when decoding index outside of DictionaryPossibly taken @jakobhok-neo4j claimed this 147 days ago. OpenType: bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
apache/arrow-java#1158 ·
Maintainers usually reply within 1 day
-
Type: enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
apache/arrow-java#1100 ·
Maintainers usually reply within 1 day
All issues in apache/arrow-java
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
apache/rocketmq-dashboard#6610 ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
MetricsHub/metricshub-community#1396 ·
Maintainers usually reply within 1 day
-
L: java:gradle L: java:maven L: ruby:bundler T: bug 🐞
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
dependabot/dependabot-core#16547 ·
Maintainers usually reply within 1 day
-
Citationcount column sorts alphabetically instead of numericallyPossibly taken @kpunia306 claimed this today. Openstatus: needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
JabRef/jabref#17459 · 4 comments ·
Maintainers usually reply within 1 day
-
A2A agent card served at agent.json, but A2A 0.3.0 uses agent-card.jsonPossibly taken @hadirsa claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
embabel/embabel-agent#2142 ·
Maintainers usually reply within 1 day