Leak detection combined with composite buffers results in incorrectly handled writerIndex when calling ByteBufUtil.writeAscii/writeUtf8 (#8153)
Motivation: We need to add special handling for WrappedCompositeByteBuf as these also extend AbstractByteBuf, otherwise we will not correctly adjust / read the writerIndex during processing. Modifications: - Add instanceof checks for WrappedCompositeByteBuf as well. - Add testcases Result: Fixes https://github.com/netty/netty/issues/8152.
This commit is contained in:
parent
0dc71cee3a
commit
9b08dbca00
@ -498,7 +498,10 @@ public final class ByteBufUtil {
|
|||||||
*/
|
*/
|
||||||
public static int reserveAndWriteUtf8(ByteBuf buf, CharSequence seq, int reserveBytes) {
|
public static int reserveAndWriteUtf8(ByteBuf buf, CharSequence seq, int reserveBytes) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (buf instanceof AbstractByteBuf) {
|
if (buf instanceof WrappedCompositeByteBuf) {
|
||||||
|
// WrappedCompositeByteBuf is a sub-class of AbstractByteBuf so it needs special handling.
|
||||||
|
buf = buf.unwrap();
|
||||||
|
} else if (buf instanceof AbstractByteBuf) {
|
||||||
AbstractByteBuf byteBuf = (AbstractByteBuf) buf;
|
AbstractByteBuf byteBuf = (AbstractByteBuf) buf;
|
||||||
byteBuf.ensureWritable0(reserveBytes);
|
byteBuf.ensureWritable0(reserveBytes);
|
||||||
int written = writeUtf8(byteBuf, byteBuf.writerIndex, seq, seq.length());
|
int written = writeUtf8(byteBuf, byteBuf.writerIndex, seq, seq.length());
|
||||||
@ -665,7 +668,10 @@ public final class ByteBufUtil {
|
|||||||
buf.writeBytes(asciiString.array(), asciiString.arrayOffset(), len);
|
buf.writeBytes(asciiString.array(), asciiString.arrayOffset(), len);
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (buf instanceof AbstractByteBuf) {
|
if (buf instanceof WrappedCompositeByteBuf) {
|
||||||
|
// WrappedCompositeByteBuf is a sub-class of AbstractByteBuf so it needs special handling.
|
||||||
|
buf = buf.unwrap();
|
||||||
|
} else if (buf instanceof AbstractByteBuf) {
|
||||||
AbstractByteBuf byteBuf = (AbstractByteBuf) buf;
|
AbstractByteBuf byteBuf = (AbstractByteBuf) buf;
|
||||||
byteBuf.ensureWritable0(len);
|
byteBuf.ensureWritable0(len);
|
||||||
int written = writeAscii(byteBuf, byteBuf.writerIndex, seq, len);
|
int written = writeAscii(byteBuf, byteBuf.writerIndex, seq, len);
|
||||||
|
@ -238,6 +238,42 @@ public class ByteBufUtilTest {
|
|||||||
buf2.unwrap().release();
|
buf2.unwrap().release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteUsAsciiComposite() {
|
||||||
|
String usAscii = "NettyRocks";
|
||||||
|
ByteBuf buf = Unpooled.buffer(16);
|
||||||
|
buf.writeBytes(usAscii.getBytes(CharsetUtil.US_ASCII));
|
||||||
|
ByteBuf buf2 = Unpooled.compositeBuffer().addComponent(
|
||||||
|
Unpooled.buffer(8)).addComponent(Unpooled.buffer(24));
|
||||||
|
// write some byte so we start writing with an offset.
|
||||||
|
buf2.writeByte(1);
|
||||||
|
ByteBufUtil.writeAscii(buf2, usAscii);
|
||||||
|
|
||||||
|
// Skip the previously written byte.
|
||||||
|
assertEquals(buf, buf2.skipBytes(1));
|
||||||
|
|
||||||
|
buf.release();
|
||||||
|
buf2.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteUsAsciiCompositeWrapped() {
|
||||||
|
String usAscii = "NettyRocks";
|
||||||
|
ByteBuf buf = Unpooled.buffer(16);
|
||||||
|
buf.writeBytes(usAscii.getBytes(CharsetUtil.US_ASCII));
|
||||||
|
ByteBuf buf2 = new WrappedCompositeByteBuf(Unpooled.compositeBuffer().addComponent(
|
||||||
|
Unpooled.buffer(8)).addComponent(Unpooled.buffer(24)));
|
||||||
|
// write some byte so we start writing with an offset.
|
||||||
|
buf2.writeByte(1);
|
||||||
|
ByteBufUtil.writeAscii(buf2, usAscii);
|
||||||
|
|
||||||
|
// Skip the previously written byte.
|
||||||
|
assertEquals(buf, buf2.skipBytes(1));
|
||||||
|
|
||||||
|
buf.release();
|
||||||
|
buf2.release();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteUtf8() {
|
public void testWriteUtf8() {
|
||||||
String usAscii = "Some UTF-8 like äÄ∏ŒŒ";
|
String usAscii = "Some UTF-8 like äÄ∏ŒŒ";
|
||||||
@ -252,6 +288,42 @@ public class ByteBufUtilTest {
|
|||||||
buf2.release();
|
buf2.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteUtf8Composite() {
|
||||||
|
String utf8 = "Some UTF-8 like äÄ∏ŒŒ";
|
||||||
|
ByteBuf buf = Unpooled.buffer(16);
|
||||||
|
buf.writeBytes(utf8.getBytes(CharsetUtil.UTF_8));
|
||||||
|
ByteBuf buf2 = Unpooled.compositeBuffer().addComponent(
|
||||||
|
Unpooled.buffer(8)).addComponent(Unpooled.buffer(24));
|
||||||
|
// write some byte so we start writing with an offset.
|
||||||
|
buf2.writeByte(1);
|
||||||
|
ByteBufUtil.writeUtf8(buf2, utf8);
|
||||||
|
|
||||||
|
// Skip the previously written byte.
|
||||||
|
assertEquals(buf, buf2.skipBytes(1));
|
||||||
|
|
||||||
|
buf.release();
|
||||||
|
buf2.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteUtf8CompositeWrapped() {
|
||||||
|
String utf8 = "Some UTF-8 like äÄ∏ŒŒ";
|
||||||
|
ByteBuf buf = Unpooled.buffer(16);
|
||||||
|
buf.writeBytes(utf8.getBytes(CharsetUtil.UTF_8));
|
||||||
|
ByteBuf buf2 = new WrappedCompositeByteBuf(Unpooled.compositeBuffer().addComponent(
|
||||||
|
Unpooled.buffer(8)).addComponent(Unpooled.buffer(24)));
|
||||||
|
// write some byte so we start writing with an offset.
|
||||||
|
buf2.writeByte(1);
|
||||||
|
ByteBufUtil.writeUtf8(buf2, utf8);
|
||||||
|
|
||||||
|
// Skip the previously written byte.
|
||||||
|
assertEquals(buf, buf2.skipBytes(1));
|
||||||
|
|
||||||
|
buf.release();
|
||||||
|
buf2.release();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteUtf8Surrogates() {
|
public void testWriteUtf8Surrogates() {
|
||||||
// leading surrogate + trailing surrogate
|
// leading surrogate + trailing surrogate
|
||||||
|
Loading…
Reference in New Issue
Block a user