From f181fbf6e47d6190ed99153e4837efc8acfb2336 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 19 Aug 2024 14:35:48 +0000 Subject: [PATCH] basic_parser returns error::header_limit ealier --- include/boost/beast/http/basic_parser.hpp | 21 +-- .../boost/beast/http/impl/basic_parser.ipp | 122 ++++++------------ test/beast/http/basic_parser.cpp | 16 +++ 3 files changed, 68 insertions(+), 91 deletions(-) diff --git a/include/boost/beast/http/basic_parser.hpp b/include/boost/beast/http/basic_parser.hpp index d2eda05f..7b890e03 100644 --- a/include/boost/beast/http/basic_parser.hpp +++ b/include/boost/beast/http/basic_parser.hpp @@ -642,25 +642,30 @@ private: error_code& ec); void - maybe_need_more( - char const* p, std::size_t n, - error_code& ec); - - void - parse_start_line( + inner_parse_start_line( char const*& p, char const* last, error_code& ec, std::true_type); void - parse_start_line( + inner_parse_start_line( char const*& p, char const* last, error_code& ec, std::false_type); void - parse_fields( + parse_start_line( + char const*& p, std::size_t n, + error_code& ec); + + void + inner_parse_fields( char const*& p, char const* last, error_code& ec); + void + parse_fields( + char const*& p, std::size_t n, + error_code& ec); + void finish_header( error_code& ec, std::true_type); diff --git a/include/boost/beast/http/impl/basic_parser.ipp b/include/boost/beast/http/impl/basic_parser.ipp index 9fd6f96f..7f23265e 100644 --- a/include/boost/beast/http/impl/basic_parser.ipp +++ b/include/boost/beast/http/impl/basic_parser.ipp @@ -111,65 +111,23 @@ loop: BOOST_FALLTHROUGH; case state::start_line: - { - maybe_need_more(p, n, ec); + parse_start_line(p, n, ec); if(ec) goto done; - parse_start_line(p, p + (std::min)( - header_limit_, n), ec, is_request{}); - if(ec) - { - if(ec == error::need_more) - { - if(n >= header_limit_) - { - BOOST_BEAST_ASSIGN_EC(ec, error::header_limit); - goto done; - } - if(p + 3 <= p1) - skip_ = static_cast< - std::size_t>(p1 - p - 3); - } - goto done; - } BOOST_ASSERT(! is_done()); n = static_cast(p1 - p); - if(p >= p1) - { - BOOST_BEAST_ASSIGN_EC(ec, error::need_more); - goto done; - } BOOST_FALLTHROUGH; - } case state::fields: - maybe_need_more(p, n, ec); + parse_fields(p, n, ec); if(ec) goto done; - parse_fields(p, p + (std::min)( - header_limit_, n), ec); - if(ec) - { - if(ec == error::need_more) - { - if(n >= header_limit_) - { - BOOST_BEAST_ASSIGN_EC(ec, error::header_limit); - goto done; - } - if(p + 3 <= p1) - skip_ = static_cast< - std::size_t>(p1 - p - 3); - } - goto done; - } finish_header(ec, is_request{}); if(ec) goto done; break; case state::body0: - BOOST_ASSERT(! skip_); this->on_body_init_impl(content_length(), ec); if(ec) goto done; @@ -177,14 +135,12 @@ loop: BOOST_FALLTHROUGH; case state::body: - BOOST_ASSERT(! skip_); parse_body(p, n, ec); if(ec) goto done; break; case state::body_to_eof0: - BOOST_ASSERT(! skip_); this->on_body_init_impl(content_length(), ec); if(ec) goto done; @@ -192,7 +148,6 @@ loop: BOOST_FALLTHROUGH; case state::body_to_eof: - BOOST_ASSERT(! skip_); parse_body_to_eof(p, n, ec); if(ec) goto done; @@ -262,39 +217,7 @@ put_eof(error_code& ec) template void basic_parser:: -maybe_need_more( - char const* p, std::size_t n, - error_code& ec) -{ - if(skip_ == 0) - return; - if( n > header_limit_) - n = header_limit_; - if(n < skip_ + 4) - { - BOOST_BEAST_ASSIGN_EC(ec, error::need_more); - return; - } - auto const term = - find_eom(p + skip_, p + n); - if(! term) - { - skip_ = n - 3; - if(skip_ + 4 > header_limit_) - { - BOOST_BEAST_ASSIGN_EC(ec, error::header_limit); - return; - } - BOOST_BEAST_ASSIGN_EC(ec, error::need_more); - return; - } - skip_ = 0; -} - -template -void -basic_parser:: -parse_start_line( +inner_parse_start_line( char const*& in, char const* last, error_code& ec, std::true_type) { @@ -351,7 +274,7 @@ parse_start_line( template void basic_parser:: -parse_start_line( +inner_parse_start_line( char const*& in, char const* last, error_code& ec, std::false_type) { @@ -409,7 +332,24 @@ parse_start_line( template void basic_parser:: -parse_fields(char const*& in, +parse_start_line( + char const*& in, std::size_t n, error_code& ec) +{ + auto const p0 = in; + + inner_parse_start_line(in, in + (std::min) + (n, header_limit_), ec, is_request{}); + if(ec == error::need_more && n >= header_limit_) + { + BOOST_BEAST_ASSIGN_EC(ec, error::header_limit); + } + header_limit_ -= static_cast(in - p0); +} + +template +void +basic_parser:: +inner_parse_fields(char const*& in, char const* last, error_code& ec) { string_view name; @@ -447,6 +387,22 @@ parse_fields(char const*& in, } } +template +void +basic_parser:: +parse_fields(char const*& in, std::size_t n, error_code& ec) +{ + auto const p0 = in; + + inner_parse_fields(in, in + (std::min) + (n, header_limit_), ec); + if(ec == error::need_more && n >= header_limit_) + { + BOOST_BEAST_ASSIGN_EC(ec, error::header_limit); + } + header_limit_ -= static_cast(in - p0); +} + template void basic_parser:: @@ -736,7 +692,7 @@ parse_chunk_header(char const*& p0, if(ec) return; p = eol; - parse_fields(p, eom, ec); + parse_fields(p, static_cast(eom - p), ec); if(ec) return; BOOST_ASSERT(p == eom); diff --git a/test/beast/http/basic_parser.cpp b/test/beast/http/basic_parser.cpp index 0a21d893..95df1bf4 100644 --- a/test/beast/http/basic_parser.cpp +++ b/test/beast/http/basic_parser.cpp @@ -843,6 +843,22 @@ public: p.put(b.data(), ec); BEAST_EXPECTS(ec == error::header_limit, ec.message()); } + { + multi_buffer b; + ostream(b) << + "POST / HTTP/1.1\r\n"; + error_code ec; + test_parser p; + p.header_limit(18); + p.eager(true); + b.consume(p.put(b.data(), ec)); + BEAST_EXPECTS(ec == error::need_more, ec.message()); + ostream(b) << + "field: value\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) <<