mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-23 11:54:42 +00:00
Read no body from an unframed request in builds without TLS too
A request with neither Content-Length nor chunked Transfer-Encoding has no body (RFC 9112 6.3), and builds with TLS support read none. Builds without it still read whatever followed such a request on a connection about to close, up to EOF, as its body. Every build now reads no body. Tests that exercised only that read, or passed whatever the server did, are removed, and a new one checks in every build that the bytes after such a request are not taken as its body.
This commit is contained in:
1 parent
fbd3e2cc9b
commit
1c91d54b7c
2 files changed
+30
-239
No files matched your search
@@ -10398,15 +10398,6 @@ inline bool has_framed_body(const Request &req) {
|
||||
req.get_header_value_u64("Content-Length") > 0;
|
||||
}
|
||||
|
||||
inline bool is_connection_persistent(const Request &req) {
|
||||
if (has_header_token(req.headers, "Connection", "close")) { return false; }
|
||||
if (req.version == "HTTP/1.0" &&
|
||||
!has_header_token(req.headers, "Connection", "keep-alive")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool expect_content(const Request &req) {
|
||||
if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" ||
|
||||
req.method == "DELETE") {
|
||||
@@ -14319,38 +14310,10 @@ inline bool Server::read_content_core(
|
||||
}
|
||||
|
||||
// RFC 9112 §6: no Transfer-Encoding and no Content-Length means no body.
|
||||
// For non-SSL builds we still scan non-persistent connections for stray
|
||||
// body bytes so the payload limit is enforced (413). On keep-alive,
|
||||
// pending bytes may be the next request (issue #2450), so skip.
|
||||
#if !defined(CPPHTTPLIB_SSL_ENABLED)
|
||||
if (!req.has_header("Content-Length") &&
|
||||
!detail::is_chunked_transfer_encoding(req.headers)) {
|
||||
if (!detail::is_connection_persistent(req) && payload_max_length_ > 0 &&
|
||||
payload_max_length_ < (std::numeric_limits<size_t>::max)()) {
|
||||
auto has_data = strm.is_readable();
|
||||
if (!has_data) {
|
||||
auto s = strm.socket();
|
||||
if (s != INVALID_SOCKET) {
|
||||
has_data = detail::select_read(s, 0, 0) > 0;
|
||||
}
|
||||
}
|
||||
if (has_data) {
|
||||
// Route through the same decompressing reader used by the
|
||||
// length-framed and chunked paths below, so payload_max_length_ is
|
||||
// enforced on the decompressed size here too instead of only on the
|
||||
// compressed wire bytes.
|
||||
return detail::read_content(strm, req, payload_max_length_, res.status,
|
||||
nullptr, out, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (!req.has_header("Content-Length") &&
|
||||
!detail::is_chunked_transfer_encoding(req.headers)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// A second read would start where the first one stopped, or in the next
|
||||
// request.
|
||||
|
||||
Reference in new issue
Block a user