From 677886f470f5ead42ce6b725efea9dfaca86194c Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 17 Jan 2013 15:10:11 +0100 Subject: [PATCH] [#907] Prevent IllegalBufferAccessException which could be triggered if inboundBufferUpdated(), flush(..), write(..) was triggered after the channel was closed --- .../channel/DefaultChannelHandlerContext.java | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java index 511884cc7e..4c4eca0704 100755 --- a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java @@ -1054,7 +1054,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements private void fireInboundBufferUpdated0() { final DefaultChannelHandlerContext next = findContextInbound(); - if (next != null) { + if (next != null && !next.isInboundBufferFreed()) { next.fillBridge(); // This comparison is safe because this method is always executed from the executor. if (next.executor == executor) { @@ -1082,7 +1082,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements } catch (Throwable t) { pipeline.notifyHandlerException(t); } finally { - if (handler instanceof ChannelInboundByteHandler) { + if (handler instanceof ChannelInboundByteHandler && !isInboundBufferFreed()) { try { ((ChannelInboundByteHandler) handler).discardInboundReadBytes(this); } catch (Throwable t) { @@ -1383,6 +1383,11 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements private void invokePrevFlush(ChannelPromise promise, Thread currentThread) { DefaultChannelHandlerContext prev = findContextOutbound(); + if (prev.isOutboundBufferFreed()) { + promise.setFailure(new ChannelPipelineException( + "Unable to flush as outbound buffer of next handler was freed already")); + return; + } prev.fillBridge(); prev.invokeFlush(promise, currentThread); } @@ -1537,6 +1542,11 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements return; } + if (isOutboundBufferFreed()) { + promise.setFailure(new ChannelPipelineException( + "Unable to write as outbound buffer of next handler was freed already")); + return; + } if (msgBuf) { outboundMessageBuffer().add(message); } else { @@ -1635,6 +1645,26 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements return channel().newFailedFuture(cause); } + private boolean isInboundBufferFreed() { + if (hasInboundByteBuffer()) { + return inboundByteBuffer().isFreed(); + } + if (hasInboundMessageBuffer()) { + return inboundMessageBuffer().isFreed(); + } + return false; + } + + private boolean isOutboundBufferFreed() { + if (hasOutboundByteBuffer()) { + return outboundByteBuffer().isFreed(); + } + if (hasOutboundMessageBuffer()) { + return outboundMessageBuffer().isFreed(); + } + return false; + } + private void validateFuture(ChannelFuture future) { if (future == null) { throw new NullPointerException("future");