Always return a real slice even when the length is 0

Motivation:

We need to always return a real slice even when the requested length is 0. This is needed as otherwise we not correctly share the reference count and so may leak a buffer if the user call release() on the returned slice and expect it to decrement the reference count of the "parent" buffer.

Modifications:

- Always return a real slice
- Add unit test for the bug.

Result:

No more leak possible when a user requests a slice of length 0 of a SlicedByteBuf.
This commit is contained in:
Norman Maurer 2015-10-16 13:38:10 +02:00
parent d5f502d940
commit 8f13e333dd
2 changed files with 24 additions and 4 deletions

View File

@ -155,9 +155,6 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
@Override
public ByteBuf slice(int index, int length) {
checkIndex(index, length);
if (length == 0) {
return Unpooled.EMPTY_BUFFER;
}
return buffer.slice(idx(index), length);
}

View File

@ -20,7 +20,7 @@ import org.junit.Test;
import java.io.IOException;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
/**
* Tests sliced channel buffers
@ -137,4 +137,27 @@ public class SlicedByteBufTest extends AbstractByteBufTest {
wrapped.release();
}
}
@Test
public void sliceEmptyNotLeak() {
ByteBuf buffer = Unpooled.buffer(8).retain();
assertEquals(2, buffer.refCnt());
ByteBuf slice1 = buffer.slice();
assertEquals(2, slice1.refCnt());
ByteBuf slice2 = slice1.slice();
assertEquals(2, slice2.refCnt());
assertFalse(slice2.release());
assertEquals(1, buffer.refCnt());
assertEquals(1, slice1.refCnt());
assertEquals(1, slice2.refCnt());
assertTrue(slice2.release());
assertEquals(0, buffer.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
}
}