Affects: 6.0.11


The DefaultDataBuffer class has follow implementations of the methods readableByteBuffers and writableByteBuffers of DataBuffer interface:

@Override
public DataBuffer.ByteBufferIterator readableByteBuffers() {
  ByteBuffer readOnly = this.byteBuffer.asReadOnlyBuffer();
  readOnly.clear().position(this.readPosition).limit(this.writePosition - this.readPosition);
  return new ByteBufferIterator(readOnly);
}
@Override
public DataBuffer.ByteBufferIterator writableByteBuffers() {
  ByteBuffer duplicate = this.byteBuffer.duplicate();
  duplicate.clear().position(this.writePosition).limit(this.capacity - this.writePosition);
  return new ByteBufferIterator(duplicate);
}

The limit on readOnly in readableByteBuffers should be set to this.writePosition, because if the condition (this.writePosition - this.readPosition) <= this.readPosition is satisfied, the limit of the returned byte buffer will be equal to its position, so the byte buffer will be returned, which no single byte could be read from. In this case the position can be set to a lower index than this.readPosition, which can lead that some buffer data will be read again, after limit increased.

The limit on duplicate in writableByteBuffers should be set to this.capacity, because if the condition (this.capacity - this.writePosition) <= this.writePosition is satisfied, the limit of the returned byte buffer will be equal to its position, so the byte buffer will be returned, which no single byte could be written into. In this case the position can be set to a lower index than this.writePosition, which can lead, that some buffer data will be overwritten, after limit increased.

So how it should be:

@Override
public DataBuffer.ByteBufferIterator readableByteBuffers() {
  ByteBuffer readOnly = this.byteBuffer.asReadOnlyBuffer().limit(this.writePosition).position(this.readPosition);
  return new ByteBufferIterator(readOnly);
}
@Override
public DataBuffer.ByteBufferIterator writableByteBuffers() {
  ByteBuffer duplicate = this.byteBuffer.duplicate().limit(this.capacity).position(this.writePosition);
  return new ByteBufferIterator(duplicate);
}

Comment From: sbrannen

Thanks for reporting the issue. We'll look into it.

Comment From: injae-kim

https://github.com/spring-projects/spring-framework/commit/0c22866b720469f7d45022ddd1a171ceffa15690

    @Override
    public DataBuffer.ByteBufferIterator readableByteBuffers() {
        ByteBuffer readOnly = this.byteBuffer
                    .slice(this.readPosition, readableByteCount()) // use slice(start, len)
                    .asReadOnlyBuffer();
        return new ByteBufferIterator(readOnly);
    }

I think this issue is fixed by above commit, so we can close this issue too~! cc. @poutsma

Comment From: poutsma

Thanks @injae-kim, closing as duplicate of #31873.