diff --git a/src/main/java/io/netty/buffer/api/CompositeBuffer.java b/src/main/java/io/netty/buffer/api/CompositeBuffer.java index 460045a..7cfbb11 100644 --- a/src/main/java/io/netty/buffer/api/CompositeBuffer.java +++ b/src/main/java/io/netty/buffer/api/CompositeBuffer.java @@ -1279,7 +1279,7 @@ final class CompositeBuffer extends RcSupport implement } return new IndexOutOfBoundsException( "Index " + index + " is out of bounds: [read 0 to " + woff + ", write 0 to " + - (capacity - 1) + "]."); + capacity + "]."); } private static IllegalStateException bufferIsClosed() { diff --git a/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java b/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java index 9d3cfdc..547a8d8 100644 --- a/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java +++ b/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java @@ -133,7 +133,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re @Override public Buffer fill(byte value) { - checkWrite(0, capacity()); + checkSet(0, capacity()); seg.fill(value); return this; } @@ -281,7 +281,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re public void copyInto(int srcPos, Buffer dest, int destPos, int length) { if (dest instanceof MemSegBuffer) { var memSegBuf = (MemSegBuffer) dest; - memSegBuf.checkWrite(destPos, length); + memSegBuf.checkSet(destPos, length); copyInto(srcPos, memSegBuf.seg, destPos, length); return; } @@ -824,7 +824,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re @Override public Buffer setMedium(int woff, int value) { - checkWrite(woff, 3); + checkSet(woff, 3); if (order == ByteOrder.BIG_ENDIAN) { setByteAtOffset(wseg, woff, (byte) (value >> 16)); setByteAtOffset(wseg, woff + 1, (byte) (value >> 8 & 0xFF)); @@ -855,7 +855,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re @Override public Buffer setUnsignedMedium(int woff, int value) { - checkWrite(woff, 3); + checkSet(woff, 3); if (order == ByteOrder.BIG_ENDIAN) { setByteAtOffset(wseg, woff, (byte) (value >> 16)); setByteAtOffset(wseg, woff + 1, (byte) (value >> 8 & 0xFF)); @@ -1100,6 +1100,12 @@ class MemSegBuffer extends RcSupport implements Buffer, Re } private void checkWrite(int index, int size) { + if (index < roff || wseg.byteSize() < index + size) { + throw writeAccessCheckException(index); + } + } + + private void checkSet(int index, int size) { if (index < 0 || wseg.byteSize() < index + size) { throw writeAccessCheckException(index); } @@ -1143,7 +1149,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re private IndexOutOfBoundsException outOfBounds(int index) { return new IndexOutOfBoundsException( "Index " + index + " is out of bounds: [read 0 to " + woff + ", write 0 to " + - (seg.byteSize() - 1) + "]."); + seg.byteSize() + "]."); } Object recoverableMemory() { diff --git a/src/test/java/io/netty/buffer/api/BufferTest.java b/src/test/java/io/netty/buffer/api/BufferTest.java index e218f0a..2f4d998 100644 --- a/src/test/java/io/netty/buffer/api/BufferTest.java +++ b/src/test/java/io/netty/buffer/api/BufferTest.java @@ -582,6 +582,28 @@ public class BufferTest { } } + @ParameterizedTest + @MethodSource("allocators") + public void setWriterOffsetMustThrowOutsideOfWritableRegion(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer buf = allocator.allocate(8)) { + // Writer offset cannot be negative. + assertThrows(IndexOutOfBoundsException.class, () -> buf.writerOffset(-1)); + + buf.writerOffset(4); + buf.readerOffset(4); + + // Cannot set writer offset before reader offset. + assertThrows(IndexOutOfBoundsException.class, () -> buf.writerOffset(3)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.writerOffset(0)); + + buf.writerOffset(buf.capacity()); + + // Cannot set writer offset beyond capacity. + assertThrows(IndexOutOfBoundsException.class, () -> buf.writerOffset(buf.capacity() + 1)); + } + } + @ParameterizedTest @MethodSource("allocators") void setReaderOffsetMustNotThrowWithinBounds(Fixture fixture) { @@ -2454,30 +2476,30 @@ public class BufferTest { } private static void verifyWriteAccessible(Buffer buf) { - buf.writerOffset(0).writeByte((byte) 32); - assertThat(buf.readerOffset(0).readByte()).isEqualTo((byte) 32); - buf.writerOffset(0).writeUnsignedByte(32); - assertThat(buf.readerOffset(0).readUnsignedByte()).isEqualTo(32); - buf.writerOffset(0).writeChar('3'); - assertThat(buf.readerOffset(0).readChar()).isEqualTo('3'); - buf.writerOffset(0).writeShort((short) 32); - assertThat(buf.readerOffset(0).readShort()).isEqualTo((short) 32); - buf.writerOffset(0).writeUnsignedShort(32); - assertThat(buf.readerOffset(0).readUnsignedShort()).isEqualTo(32); - buf.writerOffset(0).writeMedium(32); - assertThat(buf.readerOffset(0).readMedium()).isEqualTo(32); - buf.writerOffset(0).writeUnsignedMedium(32); - assertThat(buf.readerOffset(0).readUnsignedMedium()).isEqualTo(32); - buf.writerOffset(0).writeInt(32); - assertThat(buf.readerOffset(0).readInt()).isEqualTo(32); - buf.writerOffset(0).writeUnsignedInt(32); - assertThat(buf.readerOffset(0).readUnsignedInt()).isEqualTo(32L); - buf.writerOffset(0).writeFloat(3.2f); - assertThat(buf.readerOffset(0).readFloat()).isEqualTo(3.2f); - buf.writerOffset(0).writeLong(32); - assertThat(buf.readerOffset(0).readLong()).isEqualTo(32L); - buf.writerOffset(0).writeDouble(3.2); - assertThat(buf.readerOffset(0).readDouble()).isEqualTo(3.2); + buf.reset().writeByte((byte) 32); + assertThat(buf.readByte()).isEqualTo((byte) 32); + buf.reset().writerOffset(0).writeUnsignedByte(32); + assertThat(buf.readUnsignedByte()).isEqualTo(32); + buf.reset().writerOffset(0).writeChar('3'); + assertThat(buf.readChar()).isEqualTo('3'); + buf.reset().writerOffset(0).writeShort((short) 32); + assertThat(buf.readShort()).isEqualTo((short) 32); + buf.reset().writerOffset(0).writeUnsignedShort(32); + assertThat(buf.readUnsignedShort()).isEqualTo(32); + buf.reset().writerOffset(0).writeMedium(32); + assertThat(buf.readMedium()).isEqualTo(32); + buf.reset().writerOffset(0).writeUnsignedMedium(32); + assertThat(buf.readUnsignedMedium()).isEqualTo(32); + buf.reset().writerOffset(0).writeInt(32); + assertThat(buf.readInt()).isEqualTo(32); + buf.reset().writerOffset(0).writeUnsignedInt(32); + assertThat(buf.readUnsignedInt()).isEqualTo(32L); + buf.reset().writerOffset(0).writeFloat(3.2f); + assertThat(buf.readFloat()).isEqualTo(3.2f); + buf.reset().writerOffset(0).writeLong(32); + assertThat(buf.readLong()).isEqualTo(32L); + buf.reset().writerOffset(0).writeDouble(3.2); + assertThat(buf.readDouble()).isEqualTo(3.2); buf.setByte(0, (byte) 32); assertThat(buf.getByte(0)).isEqualTo((byte) 32);