From 7382a33b1eb115a730e10485e7c294a531bbe78c Mon Sep 17 00:00:00 2001 From: Bruno Leite Date: Wed, 3 Apr 2024 19:09:20 +0100 Subject: [PATCH] Fix unwrapping loop in case bytebuffer has exactly 1 handshake message In the scenario where the reading ByteBuffer only has enough bytes to unwrap one handshake message, the flow may enter a loop due to the call to ByteBuffer.clear(). That method does not actually erase any data, instead it sets the position back to 0, the limit to the capacity, and the mark is discarded. Since we are doing another unwrap attempt using the same reading ByteBuffer, the same handshake message will be read. Updating the reading ByteBuffer position instead of trying to clear it will result in a BUFFER_UNDERFLOW, which will then trigger another read from the channel (as expected). --- .../com/rabbitmq/client/impl/nio/SslEngineHelper.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/rabbitmq/client/impl/nio/SslEngineHelper.java b/src/main/java/com/rabbitmq/client/impl/nio/SslEngineHelper.java index d9a5b17105..442359c78b 100644 --- a/src/main/java/com/rabbitmq/client/impl/nio/SslEngineHelper.java +++ b/src/main/java/com/rabbitmq/client/impl/nio/SslEngineHelper.java @@ -110,6 +110,7 @@ private static SSLEngineResult.HandshakeStatus unwrap(ByteBuffer cipherIn, ByteB SSLEngineResult unwrapResult; do { int positionBeforeUnwrapping = cipherIn.position(); + LOGGER.debug("Before unwrapping cipherIn is {}, with {} remaining byte(s)", cipherIn, cipherIn.remaining()); unwrapResult = sslEngine.unwrap(cipherIn, plainIn); LOGGER.debug("SSL engine result is {} after unwrapping", unwrapResult); status = unwrapResult.getStatus(); @@ -118,14 +119,7 @@ private static SSLEngineResult.HandshakeStatus unwrap(ByteBuffer cipherIn, ByteB plainIn.clear(); if (unwrapResult.getHandshakeStatus() == NEED_TASK) { handshakeStatus = runDelegatedTasks(sslEngine); - int newPosition = positionBeforeUnwrapping + unwrapResult.bytesConsumed(); - if (newPosition == cipherIn.limit()) { - LOGGER.debug("Clearing cipherIn because all bytes have been read and unwrapped"); - cipherIn.clear(); - } else { - LOGGER.debug("Setting cipherIn position to {} (limit is {})", newPosition, cipherIn.limit()); - cipherIn.position(positionBeforeUnwrapping + unwrapResult.bytesConsumed()); - } + cipherIn.position(positionBeforeUnwrapping + unwrapResult.bytesConsumed()); } else { handshakeStatus = unwrapResult.getHandshakeStatus(); }