Affects: 5.2.12 etc (looks like bug was introduced in https://github.com/spring-projects/spring-framework/commit/db9e0b0ccb756378093d58635922c8d17aeb0815)
I'm consuming server-side events using WebClient
and experience an issue which seems to boil down to how StringDecoder
strips newlines (the event stream that I consume consist of mostly empty lines terminated by \r\n
). Basically, if a \r\n
sequence happens to get split up in two separate byte buffers, we get an IndexOutOfBoundsException
in StringDecoder
when it tries to strip out the newline (I understand it as it tries to strip 2 bytes from the current buffer but there are only 1 byte available).
I created a test case to demonstrate the issue (can be pasted right into org.springframework.core.codec.StringDecoderTests
);
@Test
void decodeNewlinesAcrossBuffers() {
Flux<DataBuffer> input = Flux.just(
stringBuffer("\r"),
stringBuffer("\n"),
stringBuffer("xyz")
);
testDecode(input, String.class, step -> step
.expectNext("")
.expectNext("xyz")
.expectComplete()
.verify());
}
When executing the above test you get the underlying exception as a suppressed exception. The relevant part of the stack trace is;
java.lang.IndexOutOfBoundsException: readerIndex: 0, writerIndex: -1 (expected: 0 <= readerIndex <= writerIndex <= capacity(1))
at io.netty.buffer.AbstractByteBuf.checkIndexBounds(AbstractByteBuf.java:112)
at io.netty.buffer.AbstractByteBuf.writerIndex(AbstractByteBuf.java:135)
at io.netty.buffer.WrappedByteBuf.writerIndex(WrappedByteBuf.java:132)
at org.springframework.core.io.buffer.NettyDataBuffer.writePosition(NettyDataBuffer.java:126)
at org.springframework.core.io.buffer.NettyDataBuffer.writePosition(NettyDataBuffer.java:43)
at org.springframework.core.codec.StringDecoder.processDataBuffer(StringDecoder.java:161)
at org.springframework.core.codec.StringDecoder.lambda$decode$0(StringDecoder.java:121)
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainSync(FluxFlattenIterable.java:552)