ByteBuf#ensureWritable(int, boolean) should not throw

Motivation:
The javadocs for ByteBuf#ensureWritable(int, boolean) indicate that it should not throw, and instead the return code should indicate the result of the operation. Due to a bug in AbstractByteBuf it is possible for a resize to be attempted on a buffer that may exceed maxCapacity() and therefore throw.

Modifications:
- If there is not enough space in the buffer, and force is false, then a resize should not be attempted

Result:
AbstractByteBuf#ensureWritable(int, boolean) enforces the javadoc constraints and does not throw.
This commit is contained in:
Scott Mitchell 2017-05-08 18:19:57 -07:00
parent 141089998f
commit 63f5cdb0d5
2 changed files with 24 additions and 7 deletions

View File

@ -295,16 +295,16 @@ public abstract class AbstractByteBuf extends ByteBuf {
return 0;
}
final int maxCapacity = maxCapacity();
final int writerIndex = writerIndex();
if (minWritableBytes > maxCapacity - writerIndex) {
if (force) {
if (capacity() == maxCapacity()) {
if (!force || capacity() == maxCapacity) {
return 1;
}
capacity(maxCapacity());
capacity(maxCapacity);
return 3;
}
}
// Normalize the current capacity to the power of 2.
int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

View File

@ -2471,6 +2471,23 @@ public abstract class AbstractByteBufTest {
buffer.release();
}
@Test
public void ensureWritableWithForceDoesNotThrow() {
ensureWritableDoesNotThrow(true);
}
@Test
public void ensureWritableWithOutForceDoesNotThrow() {
ensureWritableDoesNotThrow(false);
}
private void ensureWritableDoesNotThrow(boolean force) {
final ByteBuf buffer = newBuffer(8);
buffer.writerIndex(buffer.capacity());
buffer.ensureWritable(8, force);
buffer.release();
}
// See:
// - https://github.com/netty/netty/issues/2587
// - https://github.com/netty/netty/issues/2580