mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57: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 flagContentLength = 1<< 10;
|
||||||
static unsigned constexpr flagChunked = 1<< 11;
|
static unsigned constexpr flagChunked = 1<< 11;
|
||||||
static unsigned constexpr flagUpgrade = 1<< 12;
|
static unsigned constexpr flagUpgrade = 1<< 12;
|
||||||
static unsigned constexpr flagFinalChunk = 1<< 13;
|
|
||||||
|
|
||||||
static constexpr
|
static constexpr
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
|
@ -44,6 +44,7 @@ struct basic_parser_base
|
|||||||
chunk_header0,
|
chunk_header0,
|
||||||
chunk_header,
|
chunk_header,
|
||||||
chunk_body,
|
chunk_body,
|
||||||
|
trailer_fields,
|
||||||
complete
|
complete
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,11 +109,6 @@ struct basic_parser_base
|
|||||||
char const* it, char const* last,
|
char const* it, char const* last,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
static
|
|
||||||
char const*
|
|
||||||
find_eom(char const* p, char const* last);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
BOOST_BEAST_DECL
|
||||||
|
@ -201,40 +201,6 @@ parse_hex(char const*& it, std::uint64_t& v)
|
|||||||
return true;
|
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*
|
char const*
|
||||||
|
@ -164,6 +164,20 @@ loop:
|
|||||||
parse_chunk_header(p, n, ec);
|
parse_chunk_header(p, n, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
goto done;
|
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;
|
break;
|
||||||
|
|
||||||
case state::chunk_body:
|
case state::chunk_body:
|
||||||
@ -564,7 +578,7 @@ parse_body_to_eof(char const*& p,
|
|||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
void
|
void
|
||||||
basic_parser<isRequest>::
|
basic_parser<isRequest>::
|
||||||
parse_chunk_header(char const*& p0,
|
parse_chunk_header(char const*& in,
|
||||||
std::size_t n, error_code& ec)
|
std::size_t n, error_code& ec)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -581,101 +595,52 @@ parse_chunk_header(char const*& p0,
|
|||||||
chunk-ext-val = token / quoted-string
|
chunk-ext-val = token / quoted-string
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto p = p0;
|
auto p = in;
|
||||||
auto const pend = p + n;
|
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;
|
||||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
}
|
||||||
return;
|
if(f_ & flagExpectCRLF)
|
||||||
}
|
{
|
||||||
if(f_ & flagExpectCRLF)
|
// Treat the last CRLF in a chunk as
|
||||||
{
|
// part of the next chunk, so p can
|
||||||
// Treat the last CRLF in a chunk as
|
// be parsed in one call instead of two.
|
||||||
// part of the next chunk, so p can
|
if(! parse_crlf(p))
|
||||||
// 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::bad_chunk);
|
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk);
|
||||||
return;
|
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())
|
BOOST_BEAST_ASSIGN_EC(ec, error::body_limit);
|
||||||
{
|
|
||||||
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;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*body_limit_ -= size;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const start = p;
|
auto const start = p;
|
||||||
@ -688,20 +653,21 @@ parse_chunk_header(char const*& p0,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const ext = make_string(start, p);
|
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)
|
if(ec)
|
||||||
return;
|
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);
|
len_ = size;
|
||||||
if(ec)
|
skip_ = 0;
|
||||||
|
in = eol;
|
||||||
|
f_ |= flagExpectCRLF;
|
||||||
|
if(size != 0)
|
||||||
|
{
|
||||||
|
state_ = state::chunk_body;
|
||||||
return;
|
return;
|
||||||
state_ = state::complete;
|
}
|
||||||
|
state_ = state::trailer_fields;
|
||||||
|
header_limit_ += 2; // for the final chunk's CRLF
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
|
@ -859,6 +859,26 @@ public:
|
|||||||
BEAST_EXPECT(! p.is_done());
|
BEAST_EXPECT(! p.is_done());
|
||||||
BEAST_EXPECTS(ec == error::header_limit, ec.message());
|
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;
|
multi_buffer b;
|
||||||
ostream(b) <<
|
ostream(b) <<
|
||||||
|
@ -470,7 +470,8 @@ public:
|
|||||||
|
|
||||||
ostream(b) << "0\r\n"; // needs an extra CRLF
|
ostream(b) << "0\r\n"; // needs an extra CRLF
|
||||||
used = p.put(b.data(), ec);
|
used = p.put(b.data(), ec);
|
||||||
BEAST_EXPECT(used == 0);
|
BEAST_EXPECT(used == 3);
|
||||||
|
b.consume(used);
|
||||||
BEAST_EXPECT(ec == error::need_more);
|
BEAST_EXPECT(ec == error::need_more);
|
||||||
|
|
||||||
ostream(b) << "\r";
|
ostream(b) << "\r";
|
||||||
@ -480,7 +481,7 @@ public:
|
|||||||
|
|
||||||
ostream(b) << "\n";
|
ostream(b) << "\n";
|
||||||
used = p.put(b.data(), ec);
|
used = p.put(b.data(), ec);
|
||||||
BEAST_EXPECT(used == 5);
|
BEAST_EXPECT(used == 2);
|
||||||
BEAST_EXPECT(!ec);
|
BEAST_EXPECT(!ec);
|
||||||
BEAST_EXPECT(p.is_done());
|
BEAST_EXPECT(p.is_done());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user