From 6eff49e1fb96d7d66d10d6bd2d8dea347da6d7aa Mon Sep 17 00:00:00 2001 From: yhirose Date: Sat, 10 Jan 2026 19:23:24 -0500 Subject: [PATCH] Problem with CI test on Windows without OpenSSL (#2323) * Fix problem with 'windows without SSL` * Fix payload limit enforcement for requests without Content-Length on Windows - Enable MSG_PEEK on Windows (non-SSL builds) to detect payloads without Content-Length - Only use MSG_PEEK when payload_max_length is set to a finite value to avoid blocking - Use read_content_without_length for actual size checking to support any payload limit - Set 413 Payload Too Large status before rejecting oversized requests This fixes three test cases on Windows: - RequestWithoutContentLengthOrTransferEncoding (no payload limit) - NoContentLengthPayloadLimit (8-byte limit) - NoContentLengthExceeds10MB (10MB limit) * clang-format --- .github/workflows/test.yaml | 1 + httplib.h | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 135bf7b..59c3a29 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -156,6 +156,7 @@ jobs: -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DHTTPLIB_TEST=ON -DHTTPLIB_COMPILE=${{ matrix.config.compiled && 'ON' || 'OFF' }} + -DHTTPLIB_USE_OPENSSL_IF_AVAILABLE=${{ matrix.config.with_ssl && 'ON' || 'OFF' }} -DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_BROTLI=ON -DHTTPLIB_REQUIRE_ZSTD=ON diff --git a/httplib.h b/httplib.h index ec8d2a2..fbb38b2 100644 --- a/httplib.h +++ b/httplib.h @@ -9078,22 +9078,29 @@ inline bool Server::read_content_core( // oversized request and fail early (causing connection close). For SSL // builds we cannot reliably peek the decrypted application bytes, so keep // the original behaviour. -#if !defined(CPPHTTPLIB_OPENSSL_SUPPORT) && !defined(_WIN32) +#if !defined(CPPHTTPLIB_OPENSSL_SUPPORT) if (!req.has_header("Content-Length") && !detail::is_chunked_transfer_encoding(req.headers)) { - socket_t s = strm.socket(); - if (s != INVALID_SOCKET) { - // Peek up to payload_max_length_ + 1 bytes. If more than - // payload_max_length_ bytes are pending, reject the request. - size_t to_peek = - (payload_max_length_ > 0) - ? (std::min)(payload_max_length_ + 1, static_cast(4096)) - : 1; - std::vector peekbuf(to_peek); - ssize_t n = ::recv(s, peekbuf.data(), to_peek, MSG_PEEK); - if (n > 0 && static_cast(n) > payload_max_length_) { - // Indicate failure so connection will be closed. - return false; + // Only peek if payload_max_length is set to a finite value + if (payload_max_length_ > 0 && + payload_max_length_ < (std::numeric_limits::max)()) { + socket_t s = strm.socket(); + if (s != INVALID_SOCKET) { + // Peek to check if there is any pending data + char peekbuf[1]; + ssize_t n = ::recv(s, peekbuf, 1, MSG_PEEK); + if (n > 0) { + // There is data, so read it with payload limit enforcement + auto result = detail::read_content_without_length( + strm, payload_max_length_, out); + if (result == detail::ReadContentResult::PayloadTooLarge) { + res.status = StatusCode::PayloadTooLarge_413; + return false; + } else if (result != detail::ReadContentResult::Success) { + return false; + } + return true; + } } } return true;