diff --git a/.changes/next-release/bugfix-AWSCRTHTTPClient-7e448e2.json b/.changes/next-release/bugfix-AWSCRTHTTPClient-7e448e2.json new file mode 100644 index 000000000000..7965dc35582e --- /dev/null +++ b/.changes/next-release/bugfix-AWSCRTHTTPClient-7e448e2.json @@ -0,0 +1,6 @@ +{ + "type": "bugfix", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Fixed the issue in the AWS CRT HTTP client where the application could crash if stream.incrementWindow was invoked on a closed stream" +} diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java index 23ae027c8992..bc03f23829bb 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java @@ -95,7 +95,9 @@ public int onResponseBody(HttpStream stream, byte[] bodyBytesIn) { return; } - stream.incrementWindow(bodyBytesIn.length); + if (!responseHandlerHelper.connectionClosed().get()) { + stream.incrementWindow(bodyBytesIn.length); + } }); return 0; diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/InputStreamAdaptingHttpStreamResponseHandler.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/InputStreamAdaptingHttpStreamResponseHandler.java index 9e12d4d4679e..cd0f3183f427 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/InputStreamAdaptingHttpStreamResponseHandler.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/InputStreamAdaptingHttpStreamResponseHandler.java @@ -92,8 +92,10 @@ public int onResponseBody(HttpStream stream, byte[] bodyBytesIn) { return; } - // increment the window upon buffer consumption. - stream.incrementWindow(bodyBytesIn.length); + if (!responseHandlerHelper.connectionClosed().get()) { + // increment the window upon buffer consumption. + stream.incrementWindow(bodyBytesIn.length); + } }); // Window will be incremented after the subscriber consumes the data, returning 0 here to disable it. diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/ResponseHandlerHelper.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/ResponseHandlerHelper.java index 6b4a9c91231d..69665d1aeff9 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/ResponseHandlerHelper.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/ResponseHandlerHelper.java @@ -82,4 +82,8 @@ public void cleanUpConnectionBasedOnStatusCode(HttpStream stream) { releaseConnection(stream); } } + + public AtomicBoolean connectionClosed() { + return connectionClosed; + } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/BaseHttpStreamResponseHandlerTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/BaseHttpStreamResponseHandlerTest.java index baf126759054..d3c223901614 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/BaseHttpStreamResponseHandlerTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/BaseHttpStreamResponseHandlerTest.java @@ -16,9 +16,11 @@ package software.amazon.awssdk.http.crt.internal; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import java.nio.charset.StandardCharsets; import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -95,6 +97,22 @@ void failedToGetResponse_shouldShutdownConnection() { verify(httpStream).close(); } + @Test + void streamClosed_shouldNotIncreaseStreamWindow() throws InterruptedException { + HttpHeader[] httpHeaders = getHttpHeaders(); + responseHandler.onResponseHeaders(httpStream, 500, HttpHeaderBlock.MAIN.getValue(), + httpHeaders); + responseHandler.onResponseHeadersDone(httpStream, 0); + responseHandler.onResponseBody(httpStream, "{}".getBytes(StandardCharsets.UTF_8)); + + responseHandler.onResponseComplete(httpStream, 0); + requestFuture.join(); + verify(crtConn).shutdown(); + verify(crtConn).close(); + verify(httpStream).close(); + verify(httpStream, never()).incrementWindow(anyInt()); + } + private static HttpHeader[] getHttpHeaders() { HttpHeader[] httpHeaders = new HttpHeader[1]; httpHeaders[0] = new HttpHeader("Content-Length", "1"); diff --git a/pom.xml b/pom.xml index 99ca700e0fe7..b8fb640fad2d 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ 2.2.21 1.15 1.29 - 0.29.2 + 0.29.7 5.10.0