@samitouri / QOSAMI-WSL / commits / aee18e92

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);