Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/boost/beast/http/basic_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class basic_parser
static unsigned constexpr flagContentLength = 1<< 10;
static unsigned constexpr flagChunked = 1<< 11;
static unsigned constexpr flagUpgrade = 1<< 12;
static unsigned constexpr flagTransferEncoding = 1<< 13;

static constexpr
std::uint64_t
Expand Down
12 changes: 10 additions & 2 deletions include/boost/beast/http/impl/basic_parser.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,11 @@ do_field(field f,
BOOST_BEAST_ASSIGN_EC(ec, error::multiple_content_length);
};

// conflicting field
if(f_ & flagChunked)
// conflicting field: a Transfer-Encoding was already seen, and a
// message must not carry both Transfer-Encoding and Content-Length
// regardless of the transfer coding or the order the two fields
// arrive in (RFC 7230 3.3.3).
if(f_ & (flagChunked | flagTransferEncoding))
return bad_content_length();

// Content-length may be a comma-separated list of integers
Expand Down Expand Up @@ -811,6 +814,11 @@ do_field(field f,
return;
}

// Record that a Transfer-Encoding was present so a Content-Length
// arriving afterwards is rejected the same way it would be if the
// fields arrived in the opposite order.
f_ |= flagTransferEncoding;

ec = {};
auto const v = token_list{value};
auto const p = std::find_if(v.begin(), v.end(),
Expand Down
13 changes: 13 additions & 0 deletions test/beast/http/basic_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,19 @@ class basic_parser_test : public beast::unit_test::suite
"GET / HTTP/1.0\r\n"
"Transfer-Encoding: gzip, chunked\r\n"
"\r\n0\r\n\r\n", error::bad_transfer_encoding);

// a message must not carry both Transfer-Encoding and Content-Length,
// regardless of the transfer coding or the order the fields arrive in
failgrind<test_parser<true>>(
"POST / HTTP/1.1\r\n"
"Content-Length: 5\r\n"
"Transfer-Encoding: gzip\r\n"
"\r\n", error::bad_transfer_encoding);
failgrind<test_parser<true>>(
"POST / HTTP/1.1\r\n"
"Transfer-Encoding: gzip\r\n"
"Content-Length: 5\r\n"
"\r\n", error::bad_content_length);
}

void
Expand Down
Loading