Merge pull request #10810

07f7c75 http: parse server Content-Length strictly (alhudz)

ACKs: vtnerd, selsta
This commit is contained in:
tobtoht
2026-06-29 11:42:27 +00:00
2 changed files with 24 additions and 9 deletions
@@ -30,6 +30,7 @@
#include <boost/regex.hpp>
#include "http_protocol_handler.h"
#include "string_tools.h"
#include "string_tools_lexical.h"
#include "file_io_utils.h"
#include "net_parse_helpers.h"
#include "time_helper.h"
@@ -599,15 +600,11 @@ namespace net_utils
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::get_len_from_content_lenght(const std::string& str, size_t& OUT len)
{
static const boost::regex rexp_mach_field("\\d+", boost::regex::normal);
std::string res;
boost::smatch result;
if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched))
return false;
try { len = boost::lexical_cast<size_t>(result[0]); }
catch(...) { return false; }
return true;
// Content-Length must be 1*DIGIT (RFC 7230 3.3.2). Parse the whole value
// strictly, matching the client side, so a field such as "5abc" or "0x10"
// is rejected rather than silently yielding a body length from its leading
// digits.
return string_tools::get_xtype_from_string(len, str);
}
//-----------------------------------------------------------------------------------
template<class t_connection_context>
+18
View File
@@ -875,6 +875,24 @@ TEST(HTTP, Server_Parses_First_Header_After_Split_Request_Line)
EXPECT_EQ(body, capture.requests.front().m_body);
}
TEST(HTTP, Server_Rejects_Malformed_Content_Length)
{
const std::string body = "0123456789";
for (const char* len : {"5abc", "0x10", "+10", "1 0", "abc"})
{
const auto capture = feed_http_request(
"POST /json_rpc HTTP/1.1\r\n"
"Content-Length: " + std::string(len) + "\r\n"
"Host: example.com\r\n"
"\r\n" + body
);
ASSERT_EQ(1u, capture.results.size());
EXPECT_FALSE(capture.results.front()) << "accepted Content-Length: " << len;
EXPECT_TRUE(capture.requests.empty()) << "accepted Content-Length: " << len;
}
}
TEST(HTTP, Server_Rejects_Malformed_First_Header)
{
const auto capture = feed_http_request(