Fix an NPE in AbstractHttp2StreamChannel (#9379)

Motivation:

If a read triggers a AbstractHttp2StreamChannel to close we can
get an NPE in the read loop.

Modifications:

Make sure that the inboundBuffer isn't null before attempting to
continue the loop.

Result:

No NPE.
Fixes #9337
This commit is contained in:
Bryce Anderson 2019-07-17 12:12:19 -06:00 committed by Norman Maurer
parent e8ab79f34d
commit dd1785ba66
2 changed files with 37 additions and 1 deletions

View File

@ -783,7 +783,7 @@ abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements
do {
flowControlledBytes += doRead0((Http2Frame) message, allocHandle);
} while ((readEOS || (continueReading = allocHandle.continueReading())) &&
(message = inboundBuffer.poll()) != null);
inboundBuffer != null && (message = inboundBuffer.poll()) != null);
if (continueReading && isParentReadInProgress() && !readEOS) {
// Currently the parent and child channel are on the same EventLoop thread. If the parent is

View File

@ -303,6 +303,42 @@ public abstract class Http2MultiplexTest<C extends Http2FrameCodec> {
verifyFramesMultiplexedToCorrectChannel(childChannel, inboundHandler, 2);
}
@Test
public void channelReadShouldRespectAutoReadAndNotProduceNPE() throws Exception {
LastInboundHandler inboundHandler = new LastInboundHandler();
Http2StreamChannel childChannel = newInboundStream(3, false, inboundHandler);
assertTrue(childChannel.config().isAutoRead());
Http2HeadersFrame headersFrame = inboundHandler.readInbound();
assertNotNull(headersFrame);
childChannel.config().setAutoRead(false);
childChannel.pipeline().addFirst(new ChannelInboundHandlerAdapter() {
private int count;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
// Close channel after 2 reads so there is still something in the inboundBuffer when the close happens.
if (++count == 2) {
ctx.close();
}
}
});
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("hello world"), 0, false);
Http2DataFrame dataFrame0 = inboundHandler.readInbound();
assertNotNull(dataFrame0);
release(dataFrame0);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("foo"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("bar"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("bar"), 0, false);
assertNull(inboundHandler.readInbound());
childChannel.config().setAutoRead(true);
verifyFramesMultiplexedToCorrectChannel(childChannel, inboundHandler, 3);
inboundHandler.checkException();
}
@Test
public void readInChannelReadWithoutAutoRead() {
useReadWithoutAutoRead(false);