Correctly throw IndexOutOfBoundsException when dst.remaining() is too big.
Motivation: In some ByteBuf implementations we not correctly implement getBytes(index, ByteBuffer). Modifications: Correct code to do what is defined in the javadocs and adding test. Result: Implementation works as described.
This commit is contained in:
parent
bcea25cc52
commit
ed931b19bb
@ -132,8 +132,7 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
||||||
checkIndex(index);
|
checkIndex(index, dst.remaining());
|
||||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
|
||||||
ByteBuffer tmpBuf;
|
ByteBuffer tmpBuf;
|
||||||
if (internal) {
|
if (internal) {
|
||||||
tmpBuf = internalNioBuffer();
|
tmpBuf = internalNioBuffer();
|
||||||
@ -141,7 +140,7 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
|
|||||||
tmpBuf = memory.duplicate();
|
tmpBuf = memory.duplicate();
|
||||||
}
|
}
|
||||||
index = idx(index);
|
index = idx(index);
|
||||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
tmpBuf.clear().position(index).limit(index + dst.remaining());
|
||||||
dst.put(tmpBuf);
|
dst.put(tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ByteBuf getBytes(int index, ByteBuffer dst) {
|
public final ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
checkIndex(index);
|
checkIndex(index, dst.remaining());
|
||||||
dst.put(memory, idx(index), Math.min(capacity() - index, dst.remaining()));
|
dst.put(memory, idx(index), dst.remaining());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,19 +316,15 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
private void getBytes(int index, ByteBuffer dst, boolean internal) {
|
||||||
checkIndex(index);
|
checkIndex(index, dst.remaining());
|
||||||
if (dst == null) {
|
|
||||||
throw new NullPointerException("dst");
|
|
||||||
}
|
|
||||||
|
|
||||||
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
|
|
||||||
ByteBuffer tmpBuf;
|
ByteBuffer tmpBuf;
|
||||||
if (internal) {
|
if (internal) {
|
||||||
tmpBuf = internalNioBuffer();
|
tmpBuf = internalNioBuffer();
|
||||||
} else {
|
} else {
|
||||||
tmpBuf = buffer.duplicate();
|
tmpBuf = buffer.duplicate();
|
||||||
}
|
}
|
||||||
tmpBuf.clear().position(index).limit(index + bytesToCopy);
|
tmpBuf.clear().position(index).limit(index + dst.remaining());
|
||||||
dst.put(tmpBuf);
|
dst.put(tmpBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +179,8 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
ensureAccessible();
|
checkIndex(index, dst.remaining());
|
||||||
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
|
dst.put(array, index, dst.remaining());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,9 +318,8 @@ final class UnsafeByteBufUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
|
static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
|
||||||
buf.checkIndex(index);
|
buf.checkIndex(index, dst.remaining());
|
||||||
int bytesToCopy = Math.min(buf.capacity() - index, dst.remaining());
|
if (dst.remaining() == 0) {
|
||||||
if (bytesToCopy == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,12 +330,12 @@ final class UnsafeByteBufUtil {
|
|||||||
}
|
}
|
||||||
// Copy to direct memory
|
// Copy to direct memory
|
||||||
long dstAddress = PlatformDependent.directBufferAddress(dst);
|
long dstAddress = PlatformDependent.directBufferAddress(dst);
|
||||||
PlatformDependent.copyMemory(addr, dstAddress + dst.position(), bytesToCopy);
|
PlatformDependent.copyMemory(addr, dstAddress + dst.position(), dst.remaining());
|
||||||
dst.position(dst.position() + bytesToCopy);
|
dst.position(dst.position() + dst.remaining());
|
||||||
} else if (dst.hasArray()) {
|
} else if (dst.hasArray()) {
|
||||||
// Copy to array
|
// Copy to array
|
||||||
PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
|
PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), dst.remaining());
|
||||||
dst.position(dst.position() + bytesToCopy);
|
dst.position(dst.position() + dst.remaining());
|
||||||
} else {
|
} else {
|
||||||
dst.put(buf.nioBuffer());
|
dst.put(buf.nioBuffer());
|
||||||
}
|
}
|
||||||
|
@ -2608,6 +2608,20 @@ public abstract class AbstractByteBufTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testGetBytesByteBuffer() {
|
||||||
|
byte[] bytes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
||||||
|
// Ensure destination buffer is bigger then what is in the ByteBuf.
|
||||||
|
ByteBuffer nioBuffer = ByteBuffer.allocate(bytes.length + 1);
|
||||||
|
ByteBuf buffer = newBuffer(bytes.length);
|
||||||
|
try {
|
||||||
|
buffer.writeBytes(bytes);
|
||||||
|
buffer.getBytes(buffer.readerIndex(), nioBuffer);
|
||||||
|
} finally {
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void testRefCnt0(final boolean parameter) throws Exception {
|
private void testRefCnt0(final boolean parameter) throws Exception {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
@ -19,6 +19,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@ -184,4 +185,18 @@ public class SlicedByteBufTest extends AbstractByteBufTest {
|
|||||||
assertEquals(0, slice1.refCnt());
|
assertEquals(0, slice1.refCnt());
|
||||||
assertEquals(0, slice2.refCnt());
|
assertEquals(0, slice2.refCnt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testGetBytesByteBuffer() {
|
||||||
|
byte[] bytes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
||||||
|
// Ensure destination buffer is bigger then what is wrapped in the ByteBuf.
|
||||||
|
ByteBuffer nioBuffer = ByteBuffer.allocate(bytes.length + 1);
|
||||||
|
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(bytes).slice(0, bytes.length - 1);
|
||||||
|
try {
|
||||||
|
wrappedBuffer.getBytes(wrappedBuffer.readerIndex(), nioBuffer);
|
||||||
|
} finally {
|
||||||
|
wrappedBuffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -646,4 +646,30 @@ public class UnpooledTest {
|
|||||||
assertEquals(0, buffer4.refCnt());
|
assertEquals(0, buffer4.refCnt());
|
||||||
assertEquals(0, wrapped.refCnt());
|
assertEquals(0, wrapped.refCnt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testGetBytesByteBuffer() {
|
||||||
|
byte[] bytes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
||||||
|
// Ensure destination buffer is bigger then what is wrapped in the ByteBuf.
|
||||||
|
ByteBuffer nioBuffer = ByteBuffer.allocate(bytes.length + 1);
|
||||||
|
ByteBuf wrappedBuffer = wrappedBuffer(bytes);
|
||||||
|
try {
|
||||||
|
wrappedBuffer.getBytes(wrappedBuffer.readerIndex(), nioBuffer);
|
||||||
|
} finally {
|
||||||
|
wrappedBuffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
|
public void testGetBytesByteBuffer2() {
|
||||||
|
byte[] bytes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
||||||
|
// Ensure destination buffer is bigger then what is wrapped in the ByteBuf.
|
||||||
|
ByteBuffer nioBuffer = ByteBuffer.allocate(bytes.length + 1);
|
||||||
|
ByteBuf wrappedBuffer = wrappedBuffer(bytes, 0, bytes.length);
|
||||||
|
try {
|
||||||
|
wrappedBuffer.getBytes(wrappedBuffer.readerIndex(), nioBuffer);
|
||||||
|
} finally {
|
||||||
|
wrappedBuffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user