Fix bounds checking bugs when setting bytes

These should not take the read offset into account.
This commit is contained in:
Chris Vest 2021-03-09 16:16:38 +01:00
parent da70f29ff4
commit 2dee6f8516
3 changed files with 58 additions and 30 deletions

View File

@ -1279,7 +1279,7 @@ final class CompositeBuffer extends RcSupport<Buffer, CompositeBuffer> implement
}
return new IndexOutOfBoundsException(
"Index " + index + " is out of bounds: [read 0 to " + woff + ", write 0 to " +
(capacity - 1) + "].");
capacity + "].");
}
private static IllegalStateException bufferIsClosed() {

View File

@ -133,7 +133,7 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> 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<Buffer, MemSegBuffer> 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<Buffer, MemSegBuffer> 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<Buffer, MemSegBuffer> 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<Buffer, MemSegBuffer> 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<Buffer, MemSegBuffer> 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() {

View File

@ -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);