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:
feijermu 2020-03-30 17:26:03 +08:00 committed by GitHub
parent 81513c3728
commit aed5a74e09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 7 deletions

View File

@ -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) {

View File

@ -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());
}
}