Release the ByteBuf when IOException occurs in AbstractMemoryHttpData. (#10133)
Motivation: An IOException may be thrown from InputStream.read or checkSize method, and cause the ByteBuf leak. Modification: Release the ByteBuf when IOException occurs. Result: Avoid ByteBuf leak.
This commit is contained in:
parent
81513c3728
commit
aed5a74e09
@ -66,18 +66,24 @@ public abstract class AbstractMemoryHttpData extends AbstractHttpData {
|
||||
public void setContent(InputStream inputStream) throws IOException {
|
||||
ObjectUtil.checkNotNull(inputStream, "inputStream");
|
||||
|
||||
ByteBuf buffer = buffer();
|
||||
byte[] bytes = new byte[4096 * 4];
|
||||
int read = inputStream.read(bytes);
|
||||
ByteBuf buffer = buffer();
|
||||
int written = 0;
|
||||
while (read > 0) {
|
||||
buffer.writeBytes(bytes, 0, read);
|
||||
written += read;
|
||||
checkSize(written);
|
||||
read = inputStream.read(bytes);
|
||||
try {
|
||||
int read = inputStream.read(bytes);
|
||||
while (read > 0) {
|
||||
buffer.writeBytes(bytes, 0, read);
|
||||
written += read;
|
||||
checkSize(written);
|
||||
read = inputStream.read(bytes);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
buffer.release();
|
||||
throw e;
|
||||
}
|
||||
size = written;
|
||||
if (definedSize > 0 && definedSize < size) {
|
||||
buffer.release();
|
||||
throw new IOException("Out of size: " + size + " > " + definedSize);
|
||||
}
|
||||
if (byteBuf != null) {
|
||||
|
@ -16,9 +16,15 @@
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
@ -36,6 +42,22 @@ public class AbstractMemoryHttpDataTest {
|
||||
*/
|
||||
@Test
|
||||
public void testSetContentFromStream() throws Exception {
|
||||
// definedSize=0
|
||||
TestHttpData test = new TestHttpData("test", UTF_8, 0);
|
||||
String contentStr = "foo_test";
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(contentStr.getBytes(UTF_8));
|
||||
buf.markReaderIndex();
|
||||
ByteBufInputStream is = new ByteBufInputStream(buf);
|
||||
try {
|
||||
test.setContent(is);
|
||||
assertFalse(buf.isReadable());
|
||||
assertEquals(test.getString(UTF_8), contentStr);
|
||||
buf.resetReaderIndex();
|
||||
assertTrue(ByteBufUtil.equals(buf, test.getByteBuf()));
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
|
||||
Random random = new SecureRandom();
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
@ -56,6 +78,7 @@ public class AbstractMemoryHttpDataTest {
|
||||
assertEquals(0, buffer.readerIndex());
|
||||
assertEquals(bytes.length, buffer.writerIndex());
|
||||
assertArrayEquals(bytes, Arrays.copyOf(buffer.array(), bytes.length));
|
||||
assertArrayEquals(bytes, data.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user