Skip to content

Commit b8e25e0

Browse files
authored
SslHandler: Ensure buffers are never leaked when wrap(...) produce SS… (#14647)
…LException Motivation: After we removed the ByteBuf from the pendingUnencryptedWrites queue we need to ensure we will always release ByteBuf even in the case of wrapMultiple(...) or wrap(...) throwing a SSLException. Modifications: - Ensure we release the ByteBuf when a SSLException is thrown before rethrowing it. Result: Fixes #14644
1 parent 9f0b38b commit b8e25e0

1 file changed

Lines changed: 31 additions & 19 deletions

File tree

handler/src/main/java/io/netty/handler/ssl/SslHandler.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -852,27 +852,39 @@ private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLExcepti
852852

853853
SSLEngineResult result;
854854

855-
if (buf.readableBytes() > MAX_PLAINTEXT_LENGTH) {
856-
// If we pulled a buffer larger than the supported packet size, we can slice it up and iteratively,
857-
// encrypting multiple packets into a single larger buffer. This substantially saves on allocations
858-
// for large responses. Here we estimate how large of a buffer we need. If we overestimate a bit,
859-
// that's fine. If we underestimate, we'll simply re-enqueue the remaining buffer and get it on the
860-
// next outer loop.
861-
int readableBytes = buf.readableBytes();
862-
int numPackets = readableBytes / MAX_PLAINTEXT_LENGTH;
863-
if (readableBytes % MAX_PLAINTEXT_LENGTH != 0) {
864-
numPackets += 1;
865-
}
855+
try {
856+
if (buf.readableBytes() > MAX_PLAINTEXT_LENGTH) {
857+
// If we pulled a buffer larger than the supported packet size, we can slice it up and
858+
// iteratively, encrypting multiple packets into a single larger buffer. This substantially
859+
// saves on allocations for large responses. Here we estimate how large of a buffer we need.
860+
// If we overestimate a bit, that's fine. If we underestimate, we'll simply re-enqueue the
861+
// remaining buffer and get it on the next outer loop.
862+
int readableBytes = buf.readableBytes();
863+
int numPackets = readableBytes / MAX_PLAINTEXT_LENGTH;
864+
if (readableBytes % MAX_PLAINTEXT_LENGTH != 0) {
865+
numPackets += 1;
866+
}
866867

867-
if (out == null) {
868-
out = allocateOutNetBuf(ctx, readableBytes, buf.nioBufferCount() + numPackets);
869-
}
870-
result = wrapMultiple(alloc, engine, buf, out);
871-
} else {
872-
if (out == null) {
873-
out = allocateOutNetBuf(ctx, buf.readableBytes(), buf.nioBufferCount());
868+
if (out == null) {
869+
out = allocateOutNetBuf(ctx, readableBytes, buf.nioBufferCount() + numPackets);
870+
}
871+
result = wrapMultiple(alloc, engine, buf, out);
872+
} else {
873+
if (out == null) {
874+
out = allocateOutNetBuf(ctx, buf.readableBytes(), buf.nioBufferCount());
875+
}
876+
result = wrap(alloc, engine, buf, out);
874877
}
875-
result = wrap(alloc, engine, buf, out);
878+
} catch (SSLException e) {
879+
// Either wrapMultiple(...) or wrap(...) did throw. In this case we need to release the buffer
880+
// that we removed from pendingUnencryptedWrites before failing the promise and rethrowing it.
881+
// Failing to do so would result in a buffer leak.
882+
// See https://github.com/netty/netty/issues/14644
883+
//
884+
// We don't need to release out here as this is done in a finally block already.
885+
buf.release();
886+
promise.setFailure(e);
887+
throw e;
876888
}
877889

878890
if (buf.isReadable()) {

0 commit comments

Comments
 (0)