This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push:
new 7d64e7c9f SeekableInMemoryByteChannel.position(long) shouldn't throw
an IllegalArgumentException for a new positive position that's too large (#756)
7d64e7c9f is described below
commit 7d64e7c9f16180015e058809a7f4548bb1067143
Author: Gary Gregory <[email protected]>
AuthorDate: Mon Dec 8 12:39:05 2025 -0500
SeekableInMemoryByteChannel.position(long) shouldn't throw an
IllegalArgumentException for a new positive position that's too large (#756)
* SeekableInMemoryByteChannel.position(long) shouldn't throw an
IllegalArgumentException for a new positive position that's too large
* SeekableInMemoryByteChannel position and truncate now follow
SeekableByteChannel and WritableByteChannel Javadoc better
* Add comments and refactor local variable
---
.../utils/SeekableInMemoryByteChannel.java | 41 +++++++++++++---------
.../utils/SeekableInMemoryByteChannelTest.java | 25 ++++++++++---
2 files changed, 46 insertions(+), 20 deletions(-)
diff --git
a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
index 2f998c0e2..df709321e 100644
---
a/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
+++
b/src/main/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.java
@@ -47,7 +47,7 @@ public class SeekableInMemoryByteChannel implements
SeekableByteChannel {
private static final int NAIVE_RESIZE_LIMIT = Integer.MAX_VALUE >> 1;
private byte[] data;
private final AtomicBoolean closed = new AtomicBoolean();
- private int position;
+ private long position;
private int size;
/**
@@ -113,25 +113,28 @@ public long position() throws ClosedChannelException {
@Override
public SeekableByteChannel position(final long newPosition) throws
IOException {
ensureOpen();
- if (newPosition < 0L || newPosition > Integer.MAX_VALUE) {
- throw new IllegalArgumentException(String.format("Position must be
in range [0..%,d]: %,d", Integer.MAX_VALUE, newPosition));
+ if (newPosition < 0L) {
+ throw new IllegalArgumentException(String.format("New position is
negative: %,d", newPosition));
}
- position = (int) newPosition;
+ position = newPosition;
return this;
}
@Override
public int read(final ByteBuffer buf) throws IOException {
ensureOpen();
+ if (position > Integer.MAX_VALUE) {
+ return -1;
+ }
int wanted = buf.remaining();
- final int possible = size - position;
+ final int possible = size - (int) position;
if (possible <= 0) {
return -1;
}
if (wanted > possible) {
wanted = possible;
}
- buf.put(data, position, wanted);
+ buf.put(data, (int) position, wanted);
position += wanted;
return wanted;
}
@@ -160,14 +163,14 @@ public long size() throws ClosedChannelException {
@Override
public SeekableByteChannel truncate(final long newSize) throws
ClosedChannelException {
ensureOpen();
- if (newSize < 0L || newSize > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("Size must be range [0.." +
Integer.MAX_VALUE + "]");
+ if (newSize < 0L) {
+ throw new IllegalArgumentException(String.format("New size is
negative: %,d", newSize));
}
if (size > newSize) {
size = (int) newSize;
}
if (position > newSize) {
- position = (int) newSize;
+ position = newSize;
}
return this;
}
@@ -175,21 +178,27 @@ public SeekableByteChannel truncate(final long newSize)
throws ClosedChannelExce
@Override
public int write(final ByteBuffer b) throws IOException {
ensureOpen();
+ if (position > Integer.MAX_VALUE) {
+ throw new IOException("position > Integer.MAX_VALUE");
+ }
int wanted = b.remaining();
- final int possibleWithoutResize = size - position;
+ // intPos <= Integer.MAX_VALUE
+ int intPos = (int) position;
+ final int possibleWithoutResize = size - intPos;
if (wanted > possibleWithoutResize) {
- final int newSize = position + wanted;
+ final int newSize = intPos + wanted;
if (newSize < 0) { // overflow
resize(Integer.MAX_VALUE);
- wanted = Integer.MAX_VALUE - position;
+ wanted = Integer.MAX_VALUE - intPos;
} else {
resize(newSize);
}
}
- b.get(data, position, wanted);
- position += wanted;
- if (size < position) {
- size = position;
+ b.get(data, intPos, wanted);
+ // intPos + wanted is at most (Integer.MAX_VALUE - intPos) + intPos
+ position = intPos += wanted;
+ if (size < intPos) {
+ size = intPos;
}
return wanted;
}
diff --git
a/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java
b/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java
index 711ca6d2a..d1f969438 100644
---
a/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java
+++
b/src/test/java/org/apache/commons/compress/utils/SeekableInMemoryByteChannelTest.java
@@ -152,16 +152,33 @@ void testShouldThrowExceptionOnWritingToClosedChannel() {
}
@Test
- void testShouldThrowExceptionWhenSettingIncorrectPosition() {
+ void testShouldThrowWhenSettingIncorrectPosition() throws IOException {
try (SeekableInMemoryByteChannel c = new
SeekableInMemoryByteChannel()) {
- assertThrows(IllegalArgumentException.class, () ->
c.position(Integer.MAX_VALUE + 1L));
+ final ByteBuffer buffer = ByteBuffer.allocate(1);
+ c.position(c.size() + 1);
+ assertEquals(c.size() + 1, c.position());
+ assertEquals(-1, c.read(buffer));
+ c.position(Integer.MAX_VALUE + 1L);
+ assertEquals(Integer.MAX_VALUE + 1L, c.position());
+ assertEquals(-1, c.read(buffer));
+ assertThrows(IOException.class, () -> c.write(buffer));
+ assertThrows(IllegalArgumentException.class, () -> c.position(-1));
+ assertThrows(IllegalArgumentException.class, () ->
c.position(Integer.MIN_VALUE));
+ assertThrows(IllegalArgumentException.class, () ->
c.position(Long.MIN_VALUE));
}
}
@Test
- void testShouldThrowExceptionWhenTruncatingToIncorrectSize() {
+ void testShouldThrowWhenTruncatingToIncorrectSize() throws IOException {
try (SeekableInMemoryByteChannel c = new
SeekableInMemoryByteChannel()) {
- assertThrows(IllegalArgumentException.class, () ->
c.truncate(Integer.MAX_VALUE + 1L));
+ final ByteBuffer buffer = ByteBuffer.allocate(1);
+ c.truncate(c.size() + 1);
+ assertEquals(1, c.read(buffer));
+ c.truncate(Integer.MAX_VALUE + 1L);
+ assertEquals(0, c.read(buffer));
+ assertThrows(IllegalArgumentException.class, () -> c.truncate(-1));
+ assertThrows(IllegalArgumentException.class, () ->
c.truncate(Integer.MIN_VALUE));
+ assertThrows(IllegalArgumentException.class, () ->
c.truncate(Long.MIN_VALUE));
}
}