Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http::parser reports basic_fields errors #2920

Merged
merged 6 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions include/boost/beast/http/basic_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ class basic_parser
std::uint64_t len0_ = 0; // content length if known
std::unique_ptr<char[]> buf_; // temp storage
std::size_t buf_len_ = 0; // size of buf_
std::size_t skip_ = 0; // resume search here
std::uint32_t header_limit_ = 8192; // max header size
unsigned short status_ = 0; // response status
state state_ = state::nothing_yet; // initial state
Expand Down Expand Up @@ -110,7 +109,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
Expand Down Expand Up @@ -642,23 +640,28 @@ class basic_parser
error_code& ec);

void
maybe_need_more(
char const* p, std::size_t n,
error_code& ec);
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::true_type);
error_code& ec, std::false_type);

void
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, std::false_type);
error_code& ec);

void
parse_fields(
char const*& p, char const* last,
char const*& p, std::size_t n,
error_code& ec);

void
Expand Down
6 changes: 1 addition & 5 deletions include/boost/beast/http/detail/basic_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct basic_parser_base
chunk_header0,
chunk_header,
chunk_body,
trailer_fields,
complete
};

Expand Down Expand Up @@ -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
Expand Down
34 changes: 0 additions & 34 deletions include/boost/beast/http/detail/basic_parser.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -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*
Expand Down
8 changes: 7 additions & 1 deletion include/boost/beast/http/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ enum class error
unexpected end-of-file condition is encountered while trying
to read from the file.
*/
short_read
short_read,

/// Header field name exceeds @ref basic_fields::max_name_size.
header_field_name_too_large,

/// Header field value exceeds @ref basic_fields::max_value_size.
header_field_value_too_large
};

} // http
Expand Down
109 changes: 89 additions & 20 deletions include/boost/beast/http/fields.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
#ifndef BOOST_BEAST_HTTP_FIELDS_HPP
#define BOOST_BEAST_HTTP_FIELDS_HPP

#include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/http/field.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/core/empty_value.hpp>
Expand Down Expand Up @@ -218,6 +219,14 @@ class basic_fields


public:
/// Maximum field name size
static std::size_t constexpr max_name_size =
(std::numeric_limits<std::uint16_t>::max)() - 2;

/// Maximum field value size
static std::size_t constexpr max_value_size =
(std::numeric_limits<std::uint16_t>::max)() - 2;

/// Destructor
~basic_fields();

Expand Down Expand Up @@ -434,13 +443,15 @@ class basic_fields

@param name The field name.

@param value The value of the field, as a @ref boost::beast::string_view
@param value The field value.

@throws boost::system::system_error Thrown if an error occurs:
ashtum marked this conversation as resolved.
Show resolved Hide resolved
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
insert(field name, string_view const& value);
insert(field name, string_view value);

/* Set a field from a null pointer (deleted).
*/
void
insert(field, std::nullptr_t) = delete;

Expand All @@ -453,13 +464,17 @@ class basic_fields

@param name The field name. It is interpreted as a case-insensitive string.

@param value The value of the field, as a @ref boost::beast::string_view
@param value The field value.

@throws boost::system::system_error Thrown if an error occurs:
@li If the size of @c name exceeds @ref max_name_size, the
error code will be @ref error::header_field_name_too_large.
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
insert(string_view name, string_view const& value);
insert(string_view name, string_view value);

/* Insert a field from a null pointer (deleted).
*/
void
insert(string_view, std::nullptr_t) = delete;

Expand All @@ -477,29 +492,65 @@ class basic_fields
must be equal to `to_string(name)` using a case-insensitive
comparison, otherwise the behavior is undefined.

@param value The value of the field, as a @ref boost::beast::string_view
@param value The field value.

@throws boost::system::system_error Thrown if an error occurs:
@li If the size of @c name_string exceeds @ref max_name_size,
the error code will be @ref error::header_field_name_too_large.
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
insert(field name, string_view name_string,
string_view const& value);
string_view value);

void
insert(field, string_view, std::nullptr_t) = delete;

/** Insert a field.

If one or more fields with the same name already exist,
the new field will be inserted after the last field with
the matching name, in serialization order.
The value can be an empty string.

@param name The field name.

@param name_string The literal text corresponding to the
field name. If `name != field::unknown`, then this value
must be equal to `to_string(name)` using a case-insensitive
comparison, otherwise the behavior is undefined.

@param value The field value.

@param ec Set to indicate what error occurred:
@li If the size of @c name_string exceeds @ref max_name_size,
the error code will be @ref error::header_field_name_too_large.
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
insert(field name, string_view name_string,
string_view value, error_code& ec);

void
insert(field, string_view, std::nullptr_t, error_code& ec) = delete;
ashtum marked this conversation as resolved.
Show resolved Hide resolved

/** Set a field value, removing any other instances of that field.

First removes any values with matching field names, then
inserts the new field value. The value may be an empty string.

@param name The field name.

@param value The value of the field, as a @ref boost::beast::string_view

@return The field value.
@param value The field value.

@throws boost::system::system_error Thrown if an error occurs:
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
set(field name, string_view const& value);
set(field name, string_view value);

void
set(field, std::nullptr_t) = delete;
Expand All @@ -511,15 +562,21 @@ class basic_fields

@param name The field name. It is interpreted as a case-insensitive string.

@param value The value of the field, as a @ref boost::beast::string_view
@param value The field value.

@throws boost::system::system_error Thrown if an error occurs:
@li If the size of @c name exceeds @ref max_name_size, the
error code will be @ref error::header_field_name_too_large.
@li If the size of @c value exceeds @ref max_value_size, the
error code will be @ref error::header_field_value_too_large.
*/
void
set(string_view name, string_view const& value);
set(string_view name, string_view value);

void
set(string_view, std::nullptr_t) = delete;

/** Remove a field.
/** Remove a field.

References and iterators to the erased elements are
invalidated. Other references and iterators are not
Expand Down Expand Up @@ -744,9 +801,21 @@ class basic_fields
template<class OtherAlloc>
friend class basic_fields;

element*
try_create_new_element(
field name,
string_view sname,
string_view value,
error_code& ec);

element&
new_element(field name,
string_view sname, string_view value);
new_element(
ashtum marked this conversation as resolved.
Show resolved Hide resolved
field name,
string_view sname,
string_view value);

void
insert_element(element& e);

void
delete_element(element& e);
Expand Down
Loading
Loading