Skip to content

Commit dfbad57

Browse files
authored
ByteBufOutputStream.writeBytes should only write lower-order bytes (#15515)
Motivation: This is specified by the `DataOutput` interface. Modification: Reimplement `writeString` to not use `writeCharSequence` which adds substitute characters instead. Result: Fixes #15513
1 parent be53dc3 commit dfbad57

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

buffer/src/main/java/io/netty/buffer/ByteBufOutputStream.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package io.netty.buffer;
1717

18-
import io.netty.util.CharsetUtil;
1918
import io.netty.util.internal.ObjectUtil;
2019

2120
import java.io.DataOutput;
@@ -102,7 +101,16 @@ public void writeByte(int v) throws IOException {
102101

103102
@Override
104103
public void writeBytes(String s) throws IOException {
105-
buffer.writeCharSequence(s, CharsetUtil.US_ASCII);
104+
// We don't use `ByteBuf.writeCharSequence` here, because `writeBytes` is specified to only write the
105+
// lower-order by of multibyte characters (exactly one byte per character in the string), while
106+
// `writeCharSequence` will instead write a '?' replacement character.
107+
int length = s.length();
108+
buffer.ensureWritable(length);
109+
int offset = buffer.writerIndex();
110+
for (int i = 0; i < length; i++) {
111+
buffer.setByte(offset + i, (byte) s.charAt(i));
112+
}
113+
buffer.writerIndex(offset + length);
106114
}
107115

108116
@Override

buffer/src/test/java/io/netty/buffer/ByteBufStreamTest.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package io.netty.buffer;
1717

18-
import io.netty.util.ReferenceCountUtil;
1918
import org.junit.jupiter.api.Test;
2019
import org.junit.jupiter.api.function.Executable;
2120

@@ -351,4 +350,18 @@ public void testGeneralByteBufOutputStream() throws Exception {
351350
out.buffer().release();
352351
assertEquals(0, out.buffer().refCnt());
353352
}
353+
354+
@Test
355+
void writeStringMustIgnoreHigherOrderByte() throws Exception {
356+
ByteBuf buf = Unpooled.buffer();
357+
ByteBufOutputStream out = new ByteBufOutputStream(buf, false);
358+
try {
359+
out.writeBytes("√");
360+
} finally {
361+
out.close();
362+
}
363+
assertEquals(0x221A, '√'); // This is a multibyte character
364+
assertEquals(0x1A, buf.readByte()); // Only the lower-order byte is written
365+
assertEquals(0, buf.readableBytes());
366+
}
354367
}

0 commit comments

Comments
 (0)