Fix possible NPE in HttpCunkedInput if wrapped ChunkedInput.readChunk(...) return null.

Motivation:

Its completly fine for ChunkedInput.readChunk(...) to return null to indicate there is currently not any data to read. We need to handle this in HttpChunkedInput to not produce a NPE when constructing the HttpContent.

Modifications:

If readChunk(...) return null just return null as well.

Result:

No more NPE.
This commit is contained in:
Norman Maurer 2016-06-13 09:04:41 +02:00
parent 8ccc795314
commit f5eea4698d
2 changed files with 43 additions and 1 deletions

View File

@ -100,6 +100,9 @@ public class HttpChunkedInput implements ChunkedInput<HttpContent> {
} }
} else { } else {
ByteBuf buf = input.readChunk(allocator); ByteBuf buf = input.readChunk(allocator);
if (buf == null) {
return null;
}
return new DefaultHttpContent(buf); return new DefaultHttpContent(buf);
} }
} }

View File

@ -16,6 +16,8 @@
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedFile;
import io.netty.handler.stream.ChunkedInput; import io.netty.handler.stream.ChunkedInput;
@ -82,6 +84,42 @@ public class HttpChunkedInputTest {
check(new HttpChunkedInput(new ChunkedNioFile(TMP))); check(new HttpChunkedInput(new ChunkedNioFile(TMP)));
} }
@Test
public void testWrappedReturnNull() throws Exception {
HttpChunkedInput input = new HttpChunkedInput(new ChunkedInput<ByteBuf>() {
@Override
public boolean isEndOfInput() throws Exception {
return false;
}
@Override
public void close() throws Exception {
// NOOP
}
@Override
public ByteBuf readChunk(ChannelHandlerContext ctx) throws Exception {
return null;
}
@Override
public ByteBuf readChunk(ByteBufAllocator allocator) throws Exception {
return null;
}
@Override
public long length() {
return 0;
}
@Override
public long progress() {
return 0;
}
});
assertNull(input.readChunk(ByteBufAllocator.DEFAULT));
}
private static void check(ChunkedInput<?>... inputs) { private static void check(ChunkedInput<?>... inputs) {
EmbeddedChannel ch = new EmbeddedChannel(new ChunkedWriteHandler()); EmbeddedChannel ch = new EmbeddedChannel(new ChunkedWriteHandler());
@ -118,6 +156,7 @@ public class HttpChunkedInputTest {
} }
assertEquals(BYTES.length * inputs.length, read); assertEquals(BYTES.length * inputs.length, read);
assertSame("Last chunk must be DefaultLastHttpContent", LastHttpContent.EMPTY_LAST_CONTENT, lastHttpContent); assertSame("Last chunk must be LastHttpContent.EMPTY_LAST_CONTENT",
LastHttpContent.EMPTY_LAST_CONTENT, lastHttpContent);
} }
} }