Don't allocate memory to handle obs-fold

This commit is contained in:
Vinnie Falco
2017-06-11 09:58:57 -07:00
parent 6a8912a88b
commit 47f25417f3
6 changed files with 42 additions and 17 deletions

View File

@@ -1,3 +1,9 @@
Version 55:
* Don't allocate memory to handle obs-fold
--------------------------------------------------------------------------------
Version 54: Version 54:
* static_buffer coverage * static_buffer coverage

View File

@@ -60,6 +60,9 @@ namespace http {
@tparam Derived The derived class type. This is part of the @tparam Derived The derived class type. This is part of the
Curiously Recurring Template Pattern interface. Curiously Recurring Template Pattern interface.
@note If the parser encounters a field value with obs-fold
longer than 4 kilobytes in length, an error is generated.
*/ */
template<bool isRequest, class Derived> template<bool isRequest, class Derived>
class basic_parser class basic_parser
@@ -68,6 +71,9 @@ class basic_parser
template<bool OtherIsRequest, class OtherDerived> template<bool OtherIsRequest, class OtherDerived>
friend class basic_parser; friend class basic_parser;
// limit on the size of the obs-fold buffer
static std::size_t constexpr max_obs_fold = 4096;
// Message will be complete after reading header // Message will be complete after reading header
static unsigned constexpr flagSkipBody = 1<< 0; static unsigned constexpr flagSkipBody = 1<< 0;

View File

@@ -115,7 +115,10 @@ enum class error
bad_transfer_encoding, bad_transfer_encoding,
/// The chunk syntax is invalid. /// The chunk syntax is invalid.
bad_chunk bad_chunk,
/// An obs-fold exceeded an internal limit.
bad_obs_fold
}; };
} // http } // http

View File

@@ -40,12 +40,11 @@ namespace http {
as a `std::multiset`; there will be a separate value for each occurrence as a `std::multiset`; there will be a separate value for each occurrence
of the field name. of the field name.
@note Meets the requirements of @b Fields Meets the requirements of @b Fields
*/ */
template<class Allocator> template<class Allocator>
class basic_fields class basic_fields
{ {
private:
using off_t = std::uint16_t; using off_t = std::uint16_t;
public: public:

View File

@@ -8,6 +8,7 @@
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP #ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP #define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
#include <beast/core/static_string.hpp>
#include <beast/core/type_traits.hpp> #include <beast/core/type_traits.hpp>
#include <beast/core/detail/ci_char_traits.hpp> #include <beast/core/detail/ci_char_traits.hpp>
#include <beast/core/detail/clamp.hpp> #include <beast/core/detail/clamp.hpp>
@@ -701,25 +702,34 @@ parse_fields(char const*& p,
if(ec) if(ec)
return; return;
} }
std::string s; // https://stackoverflow.com/questions/686217/maximum-on-http-header-values
if(p != term) static_string<max_obs_fold> s;
try
{ {
s.append(p, term - 2); if(p != term)
p = term;
for(;;)
{ {
if(*p != ' ' && *p != '\t') s.append(p, term - 2);
break;
s.push_back(' ');
detail::skip_ows(p, term - 2);
term = find_eol(p, last, ec);
if(ec)
return;
if(p != term - 2)
s.append(p, term - 2);
p = term; p = term;
for(;;)
{
if(*p != ' ' && *p != '\t')
break;
s.push_back(' ');
detail::skip_ows(p, term - 2);
term = find_eol(p, last, ec);
if(ec)
return;
if(p != term - 2)
s.append(p, term - 2);
p = term;
}
} }
} }
catch(std::length_error const&)
{
ec = error::bad_obs_fold;
return;
}
auto const f = string_to_field(name); auto const f = string_to_field(name);
string_view const value{s.data(), s.size()}; string_view const value{s.data(), s.size()};
do_field(f, value, ec); do_field(f, value, ec);

View File

@@ -56,6 +56,7 @@ public:
case error::bad_content_length: return "bad Content-Length"; case error::bad_content_length: return "bad Content-Length";
case error::bad_transfer_encoding: return "bad Transfer-Encoding"; case error::bad_transfer_encoding: return "bad Transfer-Encoding";
case error::bad_chunk: return "bad chunk"; case error::bad_chunk: return "bad chunk";
case error::bad_obs_fold: return "bad obs-fold";
} }
} }