From dfe83c6dfc9b0827375342b918fae6d30f977db8 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Tue, 4 Oct 2022 17:39:53 +0100 Subject: [PATCH 1/2] Handle ResponseAccumulator not being able to buffer large response in memory ## Motivation If the response being buffered by the `ResponseAccumulator` is too large (larger than `UInt32.max`), a crash will occur. ## Modifications * Check that the number of bytes being written won't cause the buffer to go over the limit. If it does, return a failed future from `didReceiveBodyPart(task:_:)` * Created a new `ResponseTooBigError` to be used with the failed future. ## Result Will now fail graciously if too big a response is buffered in memory via the `ResponseAccumulator`. --- Sources/AsyncHTTPClient/HTTPHandler.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/AsyncHTTPClient/HTTPHandler.swift b/Sources/AsyncHTTPClient/HTTPHandler.swift index 744139f68..f3b7a4998 100644 --- a/Sources/AsyncHTTPClient/HTTPHandler.swift +++ b/Sources/AsyncHTTPClient/HTTPHandler.swift @@ -367,6 +367,12 @@ public class ResponseAccumulator: HTTPClientResponseDelegate { case error(Error) } + struct ResponseTooBigError: Error, CustomStringConvertible { + var description: String { + return "ResponseTooBigError: writing response part would exceed internal storage capacity." + } + } + var state = State.idle let request: HTTPClient.Request @@ -397,6 +403,10 @@ public class ResponseAccumulator: HTTPClientResponseDelegate { case .head(let head): self.state = .body(head, part) case .body(let head, var body): + if body.writerIndex + part.readableBytes > UInt32.max { + return task.eventLoop.makeFailedFuture(ResponseTooBigError()) + } + // The compiler can't prove that `self.state` is dead here (and it kinda isn't, there's // a cross-module call in the way) so we need to drop the original reference to `body` in // `self.state` or we'll get a CoW. To fix that we temporarily set the state to `.end` (which From 55fd54848579ab8fb44a2e997d864228fd536146 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Tue, 4 Oct 2022 22:24:53 +0100 Subject: [PATCH 2/2] PR Changes --- Sources/AsyncHTTPClient/HTTPHandler.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/AsyncHTTPClient/HTTPHandler.swift b/Sources/AsyncHTTPClient/HTTPHandler.swift index f3b7a4998..bd0f3b2b7 100644 --- a/Sources/AsyncHTTPClient/HTTPHandler.swift +++ b/Sources/AsyncHTTPClient/HTTPHandler.swift @@ -367,8 +367,8 @@ public class ResponseAccumulator: HTTPClientResponseDelegate { case error(Error) } - struct ResponseTooBigError: Error, CustomStringConvertible { - var description: String { + public struct ResponseTooBigError: Error, CustomStringConvertible { + public var description: String { return "ResponseTooBigError: writing response part would exceed internal storage capacity." } }