Skip to content

Commit 4941d5b

Browse files
authored
Fix #2033 (#2039)
1 parent 9bbb474 commit 4941d5b

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

httplib.h

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,7 @@ inline bool is_obs_text(char c) { return 128 <= static_cast<unsigned char>(c); }
25492549
inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
25502550

25512551
inline bool is_field_content(const std::string &s) {
2552-
if (s.empty()) { return false; }
2552+
if (s.empty()) { return true; }
25532553

25542554
if (s.size() == 1) {
25552555
return is_field_vchar(s[0]);
@@ -4214,22 +4214,21 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
42144214
if (!key_len) { return false; }
42154215

42164216
auto key = std::string(beg, key_end);
4217-
auto val = case_ignore::equal(key, "Location")
4218-
? std::string(p, end)
4219-
: decode_url(std::string(p, end), false);
4220-
4221-
// NOTE: From RFC 9110:
4222-
// Field values containing CR, LF, or NUL characters are
4223-
// invalid and dangerous, due to the varying ways that
4224-
// implementations might parse and interpret those
4225-
// characters; a recipient of CR, LF, or NUL within a field
4226-
// value MUST either reject the message or replace each of
4227-
// those characters with SP before further processing or
4228-
// forwarding of that message.
4229-
static const std::string CR_LF_NUL("\r\n\0", 3);
4230-
if (val.find_first_of(CR_LF_NUL) != std::string::npos) { return false; }
4231-
4232-
fn(key, val);
4217+
// auto val = (case_ignore::equal(key, "Location") ||
4218+
// case_ignore::equal(key, "Referer"))
4219+
// ? std::string(p, end)
4220+
// : decode_url(std::string(p, end), false);
4221+
auto val = std::string(p, end);
4222+
4223+
if (!detail::fields::is_field_value(val)) { return false; }
4224+
4225+
if (case_ignore::equal(key, "Location") ||
4226+
case_ignore::equal(key, "Referer")) {
4227+
fn(key, val);
4228+
} else {
4229+
fn(key, decode_url(val, false));
4230+
}
4231+
42334232
return true;
42344233
}
42354234

@@ -4265,7 +4264,7 @@ inline bool read_headers(Stream &strm, Headers &headers) {
42654264
auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
42664265

42674266
if (!parse_header(line_reader.ptr(), end,
4268-
[&](const std::string &key, std::string &val) {
4267+
[&](const std::string &key, const std::string &val) {
42694268
headers.emplace(key, val);
42704269
})) {
42714270
return false;

test/test.cc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,7 +1866,7 @@ TEST(PathUrlEncodeTest, PathUrlEncode) {
18661866
TEST(PathUrlEncodeTest, IncludePercentEncodingLF) {
18671867
Server svr;
18681868

1869-
svr.Get("/", [](const Request &req, Response &res) {
1869+
svr.Get("/", [](const Request &req, Response &) {
18701870
EXPECT_EQ("\x0A", req.get_param_value("something"));
18711871
});
18721872

@@ -4936,8 +4936,10 @@ TEST(ServerRequestParsingTest, TrimWhitespaceFromHeaderValues) {
49364936
"Connection: close\r\n"
49374937
"\r\n";
49384938

4939-
ASSERT_TRUE(send_request(5, req));
4940-
EXPECT_EQ(header_value, "\v bar \x1B");
4939+
std::string res;
4940+
ASSERT_TRUE(send_request(5, req, &res));
4941+
EXPECT_EQ(header_value, "");
4942+
EXPECT_EQ("HTTP/1.1 400 Bad Request", res.substr(0, 24));
49414943
}
49424944

49434945
// Sends a raw request and verifies that there isn't a crash or exception.
@@ -5095,6 +5097,14 @@ TEST(ServerRequestParsingTest, InvalidFieldValueContains_CR_LF_NUL) {
50955097
EXPECT_EQ("HTTP/1.1 400 Bad Request", out.substr(0, 24));
50965098
}
50975099

5100+
TEST(ServerRequestParsingTest, InvalidFieldValueContains_LF) {
5101+
std::string out;
5102+
std::string request(
5103+
"GET /header_field_value_check HTTP/1.1\r\nTest: [\n\n\n]\r\n\r\n", 55);
5104+
test_raw_request(request, &out);
5105+
EXPECT_EQ("HTTP/1.1 400 Bad Request", out.substr(0, 24));
5106+
}
5107+
50985108
TEST(ServerRequestParsingTest, EmptyFieldValue) {
50995109
std::string out;
51005110

@@ -7984,7 +7994,7 @@ TEST(InvalidHeaderCharsTest, is_field_value) {
79847994
EXPECT_FALSE(detail::fields::is_field_value(" example_token"));
79857995
EXPECT_FALSE(detail::fields::is_field_value("example_token "));
79867996
EXPECT_TRUE(detail::fields::is_field_value("token@123"));
7987-
EXPECT_FALSE(detail::fields::is_field_value(""));
7997+
EXPECT_TRUE(detail::fields::is_field_value(""));
79887998
EXPECT_FALSE(detail::fields::is_field_value("example\rtoken"));
79897999
EXPECT_FALSE(detail::fields::is_field_value("example\ntoken"));
79908000
EXPECT_FALSE(detail::fields::is_field_value(std::string("\0", 1)));

0 commit comments

Comments
 (0)