Fix three bugs in CompositeByteBuf (#8773)

Motivation

In #8758, @doom369 reported an infinite loop bug in CompositeByteBuf
which was introduced in #8437.

This is the same small fix for that, along with fixes for two other bugs
found while re-inspecting the changes and adding unit tests.

Modification

- Replace recursive call to toComponentIndex with toComponentIndex0 as
intended
- Add missed "lastAccessed" racy cache invalidation in capacity(int)
method
- Fix incorrect determination of initial offset in non-zero cIndex case
of updateComponentOffsets method
- New unit tests for previously uncovered methods

Results

Fewer bugs.
This commit is contained in:
Nick Hill 2019-01-24 03:47:04 -08:00 committed by Norman Maurer
parent c5c318f56c
commit 9e7385ddba
2 changed files with 52 additions and 2 deletions

View File

@ -497,7 +497,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
return;
}
int nextIndex = cIndex > 0 ? components[cIndex].endOffset : 0;
int nextIndex = cIndex > 0 ? components[cIndex - 1].endOffset : 0;
for (; cIndex < size; cIndex++) {
Component c = components[cIndex];
c.reposition(nextIndex);
@ -748,6 +748,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
consolidateIfNeeded();
}
} else if (newCapacity < oldCapacity) {
lastAccessed = null;
int i = size - 1;
for (int bytesToTrim = oldCapacity - newCapacity; i >= 0; i--) {
Component c = components[i];
@ -801,7 +802,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
*/
public int toComponentIndex(int offset) {
checkIndex(offset);
return toComponentIndex(offset);
return toComponentIndex0(offset);
}
private int toComponentIndex0(int offset) {

View File

@ -135,6 +135,41 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
buf.release();
}
@Test
public void testToComponentIndex() {
CompositeByteBuf buf = (CompositeByteBuf) wrappedBuffer(new byte[]{1, 2, 3, 4, 5},
new byte[]{4, 5, 6, 7, 8, 9, 26}, new byte[]{10, 9, 8, 7, 6, 5, 33});
// spot checks
assertEquals(0, buf.toComponentIndex(4));
assertEquals(1, buf.toComponentIndex(5));
assertEquals(2, buf.toComponentIndex(15));
//Loop through each byte
byte index = 0;
while (index < buf.capacity()) {
int cindex = buf.toComponentIndex(index++);
assertTrue(cindex >= 0 && cindex < buf.numComponents());
}
buf.release();
}
@Test
public void testToByteIndex() {
CompositeByteBuf buf = (CompositeByteBuf) wrappedBuffer(new byte[]{1, 2, 3, 4, 5},
new byte[]{4, 5, 6, 7, 8, 9, 26}, new byte[]{10, 9, 8, 7, 6, 5, 33});
// spot checks
assertEquals(0, buf.toByteIndex(0));
assertEquals(5, buf.toByteIndex(1));
assertEquals(12, buf.toByteIndex(2));
buf.release();
}
@Test
public void testDiscardReadBytes3() {
ByteBuf a, b;
@ -737,6 +772,20 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
buf.release();
}
@Test
public void testRemoveComponents() {
CompositeByteBuf buf = compositeBuffer();
for (int i = 0; i < 10; i++) {
buf.addComponent(wrappedBuffer(new byte[]{1, 2}));
}
assertEquals(10, buf.numComponents());
assertEquals(20, buf.capacity());
buf.removeComponents(4, 3);
assertEquals(7, buf.numComponents());
assertEquals(14, buf.capacity());
buf.release();
}
@Test
public void testGatheringWritesHeap() throws Exception {
testGatheringWrites(buffer().order(order), buffer().order(order));