Fix setBytes when source is read-only ByteBuffer and target is pooled buffer
Motivation: The method setBytes creates temporary heap buffer when source buffer is read-only. But this temporary buffer is not used correctly and may lead to data corruption. This problem occurs when target buffer is pooled and temporary buffer arrayOffset() is not zero. Modifications: Use correct arrayOffset when calling PlatformDependent.copyMemory. Unit test was added to test this case. Result: Setting buffer content works correctly when target is pooled buffer and source is read-only ByteBuffer.
This commit is contained in:
parent
64dc03a25d
commit
f5d5039bed
@ -381,7 +381,7 @@ final class UnsafeByteBufUtil {
|
||||
try {
|
||||
byte[] tmp = tmpBuf.array();
|
||||
src.get(tmp, tmpBuf.arrayOffset(), length); // moves the src position too
|
||||
PlatformDependent.copyMemory(tmp, 0, addr, length);
|
||||
PlatformDependent.copyMemory(tmp, tmpBuf.arrayOffset(), addr, length);
|
||||
} finally {
|
||||
tmpBuf.release();
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import static io.netty.util.internal.PlatformDependent.directBufferAddress;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
public class UnsafeByteBufUtilTest {
|
||||
|
||||
@ -45,4 +47,40 @@ public class UnsafeByteBufUtilTest {
|
||||
targetBuffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetBytesOnReadOnlyByteBufferWithPooledAlloc() throws Exception {
|
||||
byte[] testData = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
int length = testData.length;
|
||||
|
||||
ByteBuffer readOnlyBuffer = ByteBuffer.wrap(testData).asReadOnlyBuffer();
|
||||
|
||||
int pageSize = 4096;
|
||||
|
||||
// create memory pool with one page
|
||||
ByteBufAllocator alloc = new PooledByteBufAllocator(true, 1, 1, pageSize, 0);
|
||||
UnpooledDirectByteBuf targetBuffer = new UnpooledDirectByteBuf(alloc, length, length);
|
||||
|
||||
ByteBuf b1 = alloc.heapBuffer(16);
|
||||
ByteBuf b2 = alloc.heapBuffer(16);
|
||||
|
||||
try {
|
||||
// just check that two following buffers share same array but different offset
|
||||
assertEquals(b1.array().length, pageSize);
|
||||
assertEquals(b1.array(), b2.array());
|
||||
assertNotEquals(b1.arrayOffset(), b2.arrayOffset());
|
||||
|
||||
UnsafeByteBufUtil.setBytes(targetBuffer, directBufferAddress(targetBuffer.nioBuffer()), 0, readOnlyBuffer);
|
||||
|
||||
byte[] check = new byte[length];
|
||||
targetBuffer.getBytes(0, check, 0, length);
|
||||
|
||||
assertArrayEquals("The byte array's copy does not equal the original", testData, check);
|
||||
} finally {
|
||||
targetBuffer.release();
|
||||
b1.release();
|
||||
b2.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user