From 87c6e69d9f74621aa86542aa9e5275c1b5eb289f Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sun, 11 Jun 2017 09:58:57 -0700 Subject: [PATCH] Don't allocate memory to handle obs-fold --- CHANGELOG.md | 6 ++++ include/beast/http/basic_parser.hpp | 6 ++++ include/beast/http/error.hpp | 5 +++- include/beast/http/fields.hpp | 3 +- include/beast/http/impl/basic_parser.ipp | 38 +++++++++++++++--------- include/beast/http/impl/error.ipp | 1 + 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f66f0412..b4429f66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 55: + +* Don't allocate memory to handle obs-fold + +-------------------------------------------------------------------------------- + Version 54: * static_buffer coverage diff --git a/include/beast/http/basic_parser.hpp b/include/beast/http/basic_parser.hpp index 86525044..6777abaf 100644 --- a/include/beast/http/basic_parser.hpp +++ b/include/beast/http/basic_parser.hpp @@ -60,6 +60,9 @@ namespace http { @tparam Derived The derived class type. This is part of the 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 class basic_parser @@ -68,6 +71,9 @@ class basic_parser template 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 static unsigned constexpr flagSkipBody = 1<< 0; diff --git a/include/beast/http/error.hpp b/include/beast/http/error.hpp index 70813f94..4240ed94 100644 --- a/include/beast/http/error.hpp +++ b/include/beast/http/error.hpp @@ -115,7 +115,10 @@ enum class error bad_transfer_encoding, /// The chunk syntax is invalid. - bad_chunk + bad_chunk, + + /// An obs-fold exceeded an internal limit. + bad_obs_fold }; } // http diff --git a/include/beast/http/fields.hpp b/include/beast/http/fields.hpp index 92ca2622..9843c9c9 100644 --- a/include/beast/http/fields.hpp +++ b/include/beast/http/fields.hpp @@ -40,12 +40,11 @@ namespace http { as a `std::multiset`; there will be a separate value for each occurrence of the field name. - @note Meets the requirements of @b Fields + Meets the requirements of @b Fields */ template class basic_fields { -private: using off_t = std::uint16_t; public: diff --git a/include/beast/http/impl/basic_parser.ipp b/include/beast/http/impl/basic_parser.ipp index bb64f7dc..84dfeac0 100644 --- a/include/beast/http/impl/basic_parser.ipp +++ b/include/beast/http/impl/basic_parser.ipp @@ -8,6 +8,7 @@ #ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP #define BEAST_HTTP_IMPL_BASIC_PARSER_IPP +#include #include #include #include @@ -701,25 +702,34 @@ parse_fields(char const*& p, if(ec) return; } - std::string s; - if(p != term) + // https://stackoverflow.com/questions/686217/maximum-on-http-header-values + static_string s; + try { - s.append(p, term - 2); - p = term; - for(;;) + if(p != term) { - 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); + s.append(p, term - 2); 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); string_view const value{s.data(), s.size()}; do_field(f, value, ec); diff --git a/include/beast/http/impl/error.ipp b/include/beast/http/impl/error.ipp index 72330914..af7236f7 100644 --- a/include/beast/http/impl/error.ipp +++ b/include/beast/http/impl/error.ipp @@ -56,6 +56,7 @@ public: case error::bad_content_length: return "bad Content-Length"; case error::bad_transfer_encoding: return "bad Transfer-Encoding"; case error::bad_chunk: return "bad chunk"; + case error::bad_obs_fold: return "bad obs-fold"; } }