apache / apache/servicecomb-java-chassis
[BUG] - Issue Title cse 2.8.20版本 org.apache.servicecomb.foundation.vertx.stream.BufferInputStream流 int read()方法读取单字节,如果读取到流末尾会抛异常IndexOutOfBoundsException
- 主要言語
- Java
- スター
- 1.9k
- フォーク
- 814
- 平均マージ
- 8日 23時間
- マージ済み PR(30日)
- 1
説明
### Steps to Reproduce
cse 2.8.20版本 org.apache.servicecomb.foundation.vertx.stream.BufferInputStream流 int read()方法读取单字节,如果读取到流末尾会抛异常IndexOutOfBoundsException
示例代码1: 单独构造失败用例
```
public class CseBufferInputStream {
public static void main(String[] args) throws IOException {
byte[] byteArray = new byte[10];
BufferedReader br = null;
try {
// 由于StsCseServerFilter要在此Filter之前执行,所以,需要重置码流,将ridx置0
InputStream inputStream = getRealInputStream(byteArray);
if (inputStream == null) {
return;
}
inputStream.reset();
while (inputStream.read() >= 0) {
;
}
} finally {
IOUtils.closeQuietly(br);
}
}
public static InputStream getRealInputStream(byte[] byteArray) {
// 创建 UnpooledSlicedByteBuf
ByteBuf slicedByteBuf = Unpooled.wrappedBuffer(byteArray);
// 创建 BufferInputStream,这个stream类型,以及里面的Buffer和真实的走CSE请求的一致
InputStream inputStream = new BufferInputStream(slicedByteBuf);
return inputStream;
}
}
```
直接执行CseBufferInputStream.main()
运行结果
org.apache.servicecomb.foundation.vertx.stream.BufferInputStream流 int read()方法读取单字节,如果读取到流末尾会抛异常IndexOutOfBoundsException

示例代码2: 实际应用
/**
* gzip解压
* @param byteArray gzip压缩数据
*
* @throws IOException IOException
*/
public static void gzipRead(byte[] byteArray) throws IOException {
BufferedReader br = null;
try {
// 由于StsCseServerFilter要在此Filter之前执行,所以,需要重置码流,将ridx置0
InputStream inputStream = getRealInputStream(byteArray);
if (inputStream == null) {
return;
}
inputStream.reset();
br = new BufferedReader(new InputStreamReader(new GZIPInputStream(inputStream), "UTF-8"));
char[] readBuff = new char[2048];
while ((br.read(readBuff)) > 0) {
}
} finally {
IOUtils.closeQuietly(br);
}
}
public static InputStream getRealInputStream(byte[] byteArray) {
// 创建 UnpooledSlicedByteBuf
ByteBuf slicedByteBuf = Unpooled.wrappedBuffer(byteArray);
// 创建 BufferInputStream,这个stream类型,以及里面的Buffer和真实的走CSE请求的一致
InputStream inputStream = new BufferInputStream(slicedByteBuf);
return inputStream;
}
调用gzipRead方法,传一个正确的gzip压缩二进制流进去, 在 java 1.8.0_432 会报错,其现象和原因同 示例1一致,
int read()方法读取单字节,如果读取到流末尾会抛异常IndexOutOfBoundsException
详细调用链见图 java 1.8.0_432 见红色流程。

### Expected Behavior
org.apache.servicecomb.foundation.vertx.stream.BufferInputStream流 实现 java.io.InputStream
没字节的时候 应该返回-1,接口定义如下

### Servicecomb Version
2.8.20
### Additional Context
_No response_
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
調査の方向性
org.apache.servicecomb.foundation.vertx.stream.BufferInputStream から始め、CseBufferInputStream.main の例を使用して問題を再現します。ラップされた ByteBuf が末尾に達したときの int read() の動作を確認し、その後、有効な gzip データを使用した gzipRead も IndexOutOfBoundsException なしで完了し、ストリームの終端で -1 が返されることを検証します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- java
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 45/100