Java: openjdk version "1.8.0_163"
OpenJDK Runtime Environment (Zulu 8.28.0.1-linux64) (build 1.8.0_163-b01)
OpenJDK 64-Bit Server VM (Zulu 8.28.0.1-linux64) (build 25.163-b01, mixed
mode)
OS: Ubuntu 18.04 Linux local 4.15.0-23-generic #25-Ubuntu SMP Wed May 23
18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
The problem is that
org.apache.tomcat.util.http.fileupload.MultipartStream.ItemInputStream#read(byte[],
int, int) method does not update pos field after reading from buffer /
stream.
Unfortunately I cannot provide full example as this is private project.
Here are sample unit tests. First reproduces the error and second use
reflection to set proper field value to simulate proper behaviour:
package org.apache.tomcat.util.http.fileupload;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import static org.assertj.core.api.Assertions.assertThat;
class ItemInputStreamTest {
@Test
void Should_Read_Bytes_But_Throws_Exception() throws IOException {
// given
byte[] bytes = new byte[]{1, 2, 3};
final ByteArrayInputStream inputStream = new
ByteArrayInputStream(bytes);
final MultipartStream.ProgressNotifier progressNotifier = new
MultipartStream.ProgressNotifier(null, 1111);
final MultipartStream multipartStream = new
MultipartStream(inputStream,
bytes,
progressNotifier);
MultipartStream.ItemInputStream itemInputStream =
multipartStream.new ItemInputStream();
// when
byte[] buffer = new byte[8196];
int result = itemInputStream.read(buffer, 0, 8196);
// then
assertThat(result).isEqualTo(3);
}
@Test
void Should_Read_Bytes_Fixed() throws IOException,
NoSuchFieldException, IllegalAccessException {
// given
byte[] bytes = new byte[]{1, 2, 3};
final ByteArrayInputStream inputStream = new
ByteArrayInputStream(bytes);
final MultipartStream.ProgressNotifier progressNotifier = new
MultipartStream.ProgressNotifier(null, 1111);
final MultipartStream multipartStream = new
MultipartStream(inputStream,
bytes,
progressNotifier);
MultipartStream.ItemInputStream itemInputStream =
multipartStream.new ItemInputStream();
Field pos = itemInputStream.getClass()
.getDeclaredField("pos");
pos.setAccessible(true);
pos.set(itemInputStream, 3);
// when
byte[] buffer = new byte[8196];
int result = itemInputStream.read(buffer, 0, 8196);
// then
assertThat(result).isEqualTo(3);
}
}