From 1abe92f5243a76446387bf9e968e53b89cdbc279 Mon Sep 17 00:00:00 2001
From: Peter Jankuliak
Date: Fri, 18 Oct 2019 10:09:49 +0200
Subject: [PATCH] Fix leftovers in basic_parser corner case:
fix #1734, close #1736
buf_.get() has size `buf_len_`, but only `size` number of octets in that
buffer is valid.
---
CHANGELOG.md | 6 ++
include/boost/beast/http/basic_parser.hpp | 2 +
.../boost/beast/http/impl/basic_parser.hpp | 4 +-
test/beast/http/basic_parser.cpp | 92 +++++++++++++++++++
4 files changed, 102 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26e9f157..502189c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+Version 274:
+
+* Fix leftovers in basic_parser corner case
+
+--------------------------------------------------------------------------------
+
Version 273:
* Squelch spurious websocket timer assert
diff --git a/include/boost/beast/http/basic_parser.hpp b/include/boost/beast/http/basic_parser.hpp
index 650e810a..023bdd7a 100644
--- a/include/boost/beast/http/basic_parser.hpp
+++ b/include/boost/beast/http/basic_parser.hpp
@@ -128,6 +128,8 @@ class basic_parser
template
friend class basic_parser;
+ friend class basic_parser_test;
+
protected:
/// Default constructor
basic_parser() = default;
diff --git a/include/boost/beast/http/impl/basic_parser.hpp b/include/boost/beast/http/impl/basic_parser.hpp
index e25be7ce..1303c5bd 100644
--- a/include/boost/beast/http/impl/basic_parser.hpp
+++ b/include/boost/beast/http/impl/basic_parser.hpp
@@ -51,9 +51,9 @@ put(ConstBufferSequence const& buffers,
}
// flatten
net::buffer_copy(net::buffer(
- buf_.get(), buf_len_), buffers);
+ buf_.get(), size), buffers);
return put(net::const_buffer{
- buf_.get(), buf_len_}, ec);
+ buf_.get(), size}, ec);
}
template
diff --git a/test/beast/http/basic_parser.cpp b/test/beast/http/basic_parser.cpp
index 49f3476e..2cfa7b9d 100644
--- a/test/beast/http/basic_parser.cpp
+++ b/test/beast/http/basic_parser.cpp
@@ -1286,6 +1286,98 @@ public:
//--------------------------------------------------------------------------
+ // https://github.com/boostorg/beast/issues/1734
+
+ void
+ testIssue1734()
+ {
+ // Ensure more than one buffer, this is to avoid an optimized path in
+ // basic_parser::put(ConstBufferSequence const&,...) which avoids
+ // buffer flattening.
+ auto multibufs = [](multi_buffer::const_buffers_type buffers) {
+ std::vector bs;
+ for (auto b : buffers_range(buffers))
+ bs.push_back(b);
+ while (std::distance(bs.begin(), bs.end()) < 2) {
+ bs.push_back({});
+ }
+ return bs;
+ };
+
+ // Buffers must be bigger than max_stack_buffer to force flattening
+ // in basic_parser::put(ConstBufferSequence const&,...)
+ std::string first_chunk_data(
+ 2 * basic_parser::max_stack_buffer + 1, 'x');
+
+ std::string second_chunk_data_part1(
+ basic_parser::max_stack_buffer + 2, 'x');
+ std::string second_chunk_data_part2(
+ basic_parser::max_stack_buffer + 1, 'x');
+
+ multi_buffer b;
+ parser p;
+ p.eager(true);
+ error_code ec;
+ std::size_t used;
+
+ ostream(b) <<
+ "HTTP/1.1 200 OK\r\n"
+ "Server: test\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n";
+
+ used = p.put(b.data(), ec);
+ b.consume(used);
+
+ BEAST_EXPECT(net::buffer_size(b.data()) == 0);
+ BEAST_EXPECTS(!ec, ec.message());
+ BEAST_EXPECT(!p.is_done());
+ BEAST_EXPECT(p.is_header_done());
+
+ ostream(b) <<
+ std::hex <<
+ first_chunk_data.size() << "\r\n" <<
+ first_chunk_data << "\r\n";
+
+ // First chunk
+ used = p.put(multibufs(b.data()), ec);
+ b.consume(used);
+
+ BEAST_EXPECTS(ec == error::need_more, ec.message());
+ BEAST_EXPECT(!p.is_done());
+
+ ostream(b) <<
+ std::hex <<
+ (second_chunk_data_part1.size() +
+ second_chunk_data_part2.size() ) << "\r\n" <<
+ second_chunk_data_part1;
+
+ // Second chunk, part 1
+ used = p.put(multibufs(b.data()), ec);
+ b.consume(used);
+
+ BEAST_EXPECTS(!ec, ec.message());
+ BEAST_EXPECT(!p.is_done());
+
+ ostream(b) <<
+ second_chunk_data_part2 << "\r\n"
+ << "0\r\n\r\n";
+
+ // Second chunk, part 2
+ used = p.put(multibufs(b.data()), ec);
+ b.consume(used);
+
+ BEAST_EXPECTS(!ec, ec.message()); // <-- Error: bad chunk
+ if(p.need_eof())
+ {
+ p.put_eof(ec);
+ BEAST_EXPECTS(! ec, ec.message());
+ }
+ BEAST_EXPECT(p.is_done());
+ }
+
+ //--------------------------------------------------------------------------
+
void
run() override
{