mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
basic_parser: apply header_limit_ to trailer headers
This commit is contained in:
committed by
Mohammad Nejati
parent
f181fbf6e4
commit
a620d4175a
@ -110,7 +110,6 @@ class basic_parser
|
||||
static unsigned constexpr flagContentLength = 1<< 10;
|
||||
static unsigned constexpr flagChunked = 1<< 11;
|
||||
static unsigned constexpr flagUpgrade = 1<< 12;
|
||||
static unsigned constexpr flagFinalChunk = 1<< 13;
|
||||
|
||||
static constexpr
|
||||
std::uint64_t
|
||||
|
@ -44,6 +44,7 @@ struct basic_parser_base
|
||||
chunk_header0,
|
||||
chunk_header,
|
||||
chunk_body,
|
||||
trailer_fields,
|
||||
complete
|
||||
};
|
||||
|
||||
@ -108,11 +109,6 @@ struct basic_parser_base
|
||||
char const* it, char const* last,
|
||||
error_code& ec);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
char const*
|
||||
find_eom(char const* p, char const* last);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
|
@ -201,40 +201,6 @@ parse_hex(char const*& it, std::uint64_t& v)
|
||||
return true;
|
||||
}
|
||||
|
||||
char const*
|
||||
basic_parser_base::
|
||||
find_eom(char const* p, char const* last)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(p + 4 > last)
|
||||
return nullptr;
|
||||
if(p[3] != '\n')
|
||||
{
|
||||
if(p[3] == '\r')
|
||||
++p;
|
||||
else
|
||||
p += 4;
|
||||
}
|
||||
else if(p[2] != '\r')
|
||||
{
|
||||
p += 4;
|
||||
}
|
||||
else if(p[1] != '\n')
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else if(p[0] != '\r')
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return p + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
char const*
|
||||
|
@ -164,6 +164,20 @@ loop:
|
||||
parse_chunk_header(p, n, ec);
|
||||
if(ec)
|
||||
goto done;
|
||||
BOOST_ASSERT(! skip_);
|
||||
if(state_ != state::trailer_fields)
|
||||
break;
|
||||
n = static_cast<std::size_t>(p1 - p);
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::trailer_fields:
|
||||
parse_fields(p, n, ec);
|
||||
if(ec)
|
||||
goto done;
|
||||
this->on_finish_impl(ec);
|
||||
if(ec)
|
||||
goto done;
|
||||
state_ = state::complete;
|
||||
break;
|
||||
|
||||
case state::chunk_body:
|
||||
@ -564,7 +578,7 @@ parse_body_to_eof(char const*& p,
|
||||
template<bool isRequest>
|
||||
void
|
||||
basic_parser<isRequest>::
|
||||
parse_chunk_header(char const*& p0,
|
||||
parse_chunk_header(char const*& in,
|
||||
std::size_t n, error_code& ec)
|
||||
{
|
||||
/*
|
||||
@ -581,101 +595,52 @@ parse_chunk_header(char const*& p0,
|
||||
chunk-ext-val = token / quoted-string
|
||||
*/
|
||||
|
||||
auto p = p0;
|
||||
auto p = in;
|
||||
auto const pend = p + n;
|
||||
char const* eol;
|
||||
|
||||
if(! (f_ & flagFinalChunk))
|
||||
if(n < skip_ + 2)
|
||||
{
|
||||
if(n < skip_ + 2)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(f_ & flagExpectCRLF)
|
||||
{
|
||||
// Treat the last CRLF in a chunk as
|
||||
// part of the next chunk, so p can
|
||||
// be parsed in one call instead of two.
|
||||
if(! parse_crlf(p))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
eol = find_eol(p0 + skip_, pend, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! eol)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
skip_ = n - 1;
|
||||
return;
|
||||
}
|
||||
skip_ = static_cast<
|
||||
std::size_t>(eol - 2 - p0);
|
||||
|
||||
std::uint64_t size;
|
||||
if(! parse_hex(p, size))
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(f_ & flagExpectCRLF)
|
||||
{
|
||||
// Treat the last CRLF in a chunk as
|
||||
// part of the next chunk, so p can
|
||||
// be parsed in one call instead of two.
|
||||
if(! parse_crlf(p))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk);
|
||||
return;
|
||||
}
|
||||
if(size != 0)
|
||||
}
|
||||
|
||||
auto const eol = find_eol(p + skip_, pend, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! eol)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
if(p != pend)
|
||||
skip_ = pend - p - 1;
|
||||
return;
|
||||
}
|
||||
skip_ = static_cast<std::size_t>(eol - p - 2);
|
||||
|
||||
std::uint64_t size;
|
||||
if(! parse_hex(p, size))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk);
|
||||
return;
|
||||
}
|
||||
if (body_limit_.has_value())
|
||||
{
|
||||
if (size > *body_limit_)
|
||||
{
|
||||
if (body_limit_.has_value())
|
||||
{
|
||||
if (size > *body_limit_)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::body_limit);
|
||||
return;
|
||||
}
|
||||
*body_limit_ -= size;
|
||||
}
|
||||
auto const start = p;
|
||||
parse_chunk_extensions(p, pend, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(p != eol -2 )
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk_extension);
|
||||
return;
|
||||
}
|
||||
auto const ext = make_string(start, p);
|
||||
this->on_chunk_header_impl(size, ext, ec);
|
||||
if(ec)
|
||||
return;
|
||||
len_ = size;
|
||||
skip_ = 2;
|
||||
p0 = eol;
|
||||
f_ |= flagExpectCRLF;
|
||||
state_ = state::chunk_body;
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::body_limit);
|
||||
return;
|
||||
}
|
||||
|
||||
f_ |= flagFinalChunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(n >= 3);
|
||||
if(f_ & flagExpectCRLF)
|
||||
{
|
||||
BOOST_ASSERT(n >= 5);
|
||||
BOOST_VERIFY(parse_crlf(p));
|
||||
}
|
||||
std::uint64_t size;
|
||||
BOOST_VERIFY(parse_hex(p, size));
|
||||
eol = find_eol(p, pend, ec);
|
||||
BOOST_ASSERT(! ec);
|
||||
}
|
||||
|
||||
auto eom = find_eom(p0 + skip_, pend);
|
||||
if(! eom)
|
||||
{
|
||||
BOOST_ASSERT(n >= 3);
|
||||
skip_ = n - 3;
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
*body_limit_ -= size;
|
||||
}
|
||||
|
||||
auto const start = p;
|
||||
@ -688,20 +653,21 @@ parse_chunk_header(char const*& p0,
|
||||
return;
|
||||
}
|
||||
auto const ext = make_string(start, p);
|
||||
this->on_chunk_header_impl(0, ext, ec);
|
||||
this->on_chunk_header_impl(size, ext, ec);
|
||||
if(ec)
|
||||
return;
|
||||
p = eol;
|
||||
parse_fields(p, static_cast<std::size_t>(eom - p), ec);
|
||||
if(ec)
|
||||
return;
|
||||
BOOST_ASSERT(p == eom);
|
||||
p0 = eom;
|
||||
|
||||
this->on_finish_impl(ec);
|
||||
if(ec)
|
||||
len_ = size;
|
||||
skip_ = 0;
|
||||
in = eol;
|
||||
f_ |= flagExpectCRLF;
|
||||
if(size != 0)
|
||||
{
|
||||
state_ = state::chunk_body;
|
||||
return;
|
||||
state_ = state::complete;
|
||||
}
|
||||
state_ = state::trailer_fields;
|
||||
header_limit_ += 2; // for the final chunk's CRLF
|
||||
}
|
||||
|
||||
template<bool isRequest>
|
||||
|
@ -859,6 +859,26 @@ public:
|
||||
BEAST_EXPECT(! p.is_done());
|
||||
BEAST_EXPECTS(ec == error::header_limit, ec.message());
|
||||
}
|
||||
{
|
||||
multi_buffer b;
|
||||
ostream(b) <<
|
||||
"POST / HTTP/1.1\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n"
|
||||
"0\r\n";
|
||||
error_code ec;
|
||||
test_parser<true> p;
|
||||
p.header_limit(47);
|
||||
p.eager(true);
|
||||
b.consume(p.put(b.data(), ec));
|
||||
BEAST_EXPECTS(ec == error::need_more, ec.message());
|
||||
ostream(b) <<
|
||||
"field: value\r\n"
|
||||
"\r\n";
|
||||
b.consume(p.put(b.data(), ec));
|
||||
BEAST_EXPECT(! p.is_done());
|
||||
BEAST_EXPECTS(ec == error::header_limit, ec.message());
|
||||
}
|
||||
{
|
||||
multi_buffer b;
|
||||
ostream(b) <<
|
||||
|
@ -470,7 +470,8 @@ public:
|
||||
|
||||
ostream(b) << "0\r\n"; // needs an extra CRLF
|
||||
used = p.put(b.data(), ec);
|
||||
BEAST_EXPECT(used == 0);
|
||||
BEAST_EXPECT(used == 3);
|
||||
b.consume(used);
|
||||
BEAST_EXPECT(ec == error::need_more);
|
||||
|
||||
ostream(b) << "\r";
|
||||
@ -480,7 +481,7 @@ public:
|
||||
|
||||
ostream(b) << "\n";
|
||||
used = p.put(b.data(), ec);
|
||||
BEAST_EXPECT(used == 5);
|
||||
BEAST_EXPECT(used == 2);
|
||||
BEAST_EXPECT(!ec);
|
||||
BEAST_EXPECT(p.is_done());
|
||||
}
|
||||
|
Reference in New Issue
Block a user