Affects: 6.*.*
The following test fails:
import static org.junit.jupiter.api.Assertions.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
class DefaultDataBufferStringTransformationTest {
@Test
void test() {
Charset charset = StandardCharsets.UTF_8;
DataBuffer dataBuffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer(DefaultDataBufferFactory.DEFAULT_INITIAL_CAPACITY);
String name = "Müller";
int repeatCount = 19;
for(int i = 0; i < repeatCount; i++) {
dataBuffer.write(name, charset);
}
String expected = name.repeat(repeatCount);
String result = dataBuffer.toString(charset);
assertEquals(expected, result);
}
}
May be it has something to do with this issue.
Comment From: sdeleuze
I can indeed reproduce:
Expected :MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
Actual :MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerler
@poutsma Maybe you want to tackle this one since it could be indeed potentially related to #30966.
Comment From: sbrannen
Out of curiosity, I took a glance at this yesterday, and I think the issue might be in DataBuffer#write(CharSequence, Charset)
instead of in DefaultDataBuffer
.
If you add System.out.println(toString(StandardCharsets.UTF_8));
to the write()
method immediately after writePosition(dest.position());
, you'll see the following.
Müller
MüllerMüller
MüllerMüllerMüller
MüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMül
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüller
MüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerMüllerler
The error occurs when the current ByteBuffer
does not contain enough remaining space to hold the content of the supplied CharSequence
and the DataBuffer
's capacity has to be increased.
In the last three lines of the above output you can see that first Mül
is written, then Mül
is gone, and then ler
is written. So the initial Mül
is effectively lost.
This occurs when adding the encoded CharSet
content of length L
to the current buffer with size B
exceeds the initial capacity C
divided by 2.
So, when B + L > C/2
.
C
= DefaultDataBufferFactory.DEFAULT_INITIAL_CAPACITY = 256.
C / 2
= 128
For the 18th iteration: B + L
= 7 * 18 = 126 (7 because ü
takes up two positions when encoded), and 127 < 128. So no error occurs.
For the 19th iteration: B + L
= 7 * 19 = 133, and 133 > 128, and content is lost as described above.