Fix potential issues in DockerHttpClient SendRequest (#40849)
yao-msft committed
Jun 22, 2026 at 12:57 UTC
aee18e92c0412425fe333bbef0d94ef606856a8c
1 file changed
+16
-5
src/windows/wslcsession/DockerHTTPClient.cpp
+16
-5
@@ -797,6 +797,8 @@ std::pair<DockerHTTPClient::HTTPResponse, wil::unique_socket> DockerHTTPClient::
797
798
// Parse the response header
799
constexpr auto bufferSize = 16 * 1024;
800
+ // Docker response header max size.
801
+ constexpr size_t maxHeaderSize = _1MB;
802
size_t Offset = 0;
803
std::vector<char> buffer;
804
http::response_parser<http::buffer_body> parser;
@@ -807,6 +809,9 @@ std::pair<DockerHTTPClient::HTTPResponse, wil::unique_socket> DockerHTTPClient::
809
// Consume the socket until the header end is reached
810
while (!parser.is_header_done())
811
{
812
+ THROW_HR_IF_MSG(
813
+ HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW), Offset >= maxHeaderSize, "HTTP response header exceeded %zu bytes", maxHeaderSize);
814
+
815
buffer.resize(Offset + bufferSize);
816
817
// Peek for the end of the HTTP header '\r\n'
@@ -815,8 +820,9 @@ std::pair<DockerHTTPClient::HTTPResponse, wil::unique_socket> DockerHTTPClient::
820
821
THROW_HR_IF(E_ABORT, bytesRead == 0);
822
818
- size_t i{};
819
- for (i = 0; i < bytesRead + Offset && lineFeeds < 2; i++)
823
+ // Scan only the newly peeked bytes [Offset, Offset + bytesRead)
824
+ size_t i = 0;
825
+ for (i = Offset; i < bytesRead + Offset && lineFeeds < 2; i++)
826
{
827
if (buffer[i] == '\n')
828
{
@@ -828,10 +834,15 @@ std::pair<DockerHTTPClient::HTTPResponse, wil::unique_socket> DockerHTTPClient::
834
}
835
}
836
831
- // Consume the buffer from the socket.
837
+ WI_ASSERT(i >= Offset);
838
+ const size_t toConsume = i - Offset;
839
+
840
+ // Consume the scanned header bytes from the socket
841
bytesRead = common::socket::Receive(
833
- context->stream.native_handle(), gsl::span(reinterpret_cast<gsl::byte*>(buffer.data() + Offset), i - Offset), m_exitingEvent);
834
- WI_ASSERT(bytesRead == i - Offset);
842
+ context->stream.native_handle(), gsl::span(reinterpret_cast<gsl::byte*>(buffer.data() + Offset), toConsume), m_exitingEvent, 0);
843
+ THROW_HR_IF(E_ABORT, bytesRead == 0); // E_ABORT case after peek but before consume
844
+ THROW_HR_IF_MSG(
845
+ E_UNEXPECTED, static_cast<size_t>(bytesRead) != toConsume, "Short read consuming HTTP header: got %d, expected %zu", bytesRead, toConsume);
846
847
Offset += bytesRead;
848
buffer.resize(Offset);