beast
beast copied to clipboard
Assertion failure "Incrementing a default-constructed iterator" when moving http::response_serializer
Version of Beast
315
(The boost version I used was 1.76.0)
Steps necessary to reproduce the problem
This program reproduces the issue:
#include <boost/beast/http/serializer.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/string_body.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/http/write.hpp>
#include <boost/asio/io_context.hpp>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <vector>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffers_iterator.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/system/error_code.hpp>
namespace mock {
template<typename Executor>
struct basic_async_write_stream {
using executor_type = Executor;
explicit basic_async_write_stream(executor_type ex) noexcept : ex_(ex) {}
auto get_executor() noexcept {
return ex_;
}
using buffer_type = std::vector<std::byte>;
const buffer_type& buffer() const noexcept {
return buffer_;
}
buffer_type& buffer() noexcept {
return buffer_;
}
template<typename ConstBufferSequence, typename CompletionToken>
auto async_write_some(ConstBufferSequence cb, CompletionToken&& token) {
using signature_type = void(boost::system::error_code, std::size_t);
auto i = [this](auto h, auto cb) {
using iterator_type = boost::asio::buffers_iterator<decltype(cb), std::byte>;
auto before = buffer_.size();
std::copy(iterator_type::begin(cb), iterator_type::end(cb), std::
back_inserter(buffer_));
auto ex = boost::asio::get_associated_executor(h, ex_);
auto alloc = boost::asio::get_associated_allocator(h);
auto c = [h = std::move(h), bytes_transferred = buffer_.size() - before]()
mutable { std::invoke(std::move(h), boost::system::error_code(),
bytes_transferred); };
ex.post(std::move(c), alloc);
};
return boost::asio::async_initiate<CompletionToken, signature_type>(std::move(i),
token, std::move(cb));
}
private:
executor_type ex_;
buffer_type buffer_;
};
using async_write_stream = basic_async_write_stream<boost::asio::io_context::
executor_type>;
}
int main(int, char**) {
boost::beast::http::response<boost::beast::http::string_body> response{boost::beast::http::status::ok, 11};
boost::beast::http::response_serializer<boost::beast::http::string_body> serializer{response};
boost::asio::io_context io_context{};
mock::async_write_stream write_stream{io_context.get_executor()};
boost::beast::http::async_write_header(
write_stream, serializer,
[](boost::system::error_code, std::size_t) {
});
io_context.run();
boost::beast::http::response_serializer<boost::beast::http::string_body> serializer2{std::move(serializer)};
}
The output of the program is:
a.out: /home/enolan/beast/include/boost/beast/core/impl/buffers_cat.hpp:209: void boost::beast::buffers_cat_view<Buffers>::const_iterator::increment::operator()(boost::mp11::mp_size_t<0>) [with Bn = {boost::asio::const_buffer, boost::asio::const_buffer, boost::asio::const_buffer, boost::beast::http::basic_fields<std::allocator<char> >::writer::field_range, boost::beast::http::chunk_crlf}; boost::mp11::mp_size_t<0> = std::integral_constant<long unsigned int, 0>]: Assertion `(false)&&("Incrementing a default-constructed iterator")' failed.
Aborted (core dumped)
The assertion failure happens inside the move constructor of serializer2.
All relevant compiler information
Compiled on Ubuntu 21.04 with GCC 10.3 using the following command line:
g++ -std=c++17 -I$HOME/beast/include -I$HOME/boost_1_76_0 ./main.cpp -lpthread
Are you sure your mock stream stream is correct? Have you tried it with a simple asio composed write?
Here is an alternative reproduction without the mock async write stream, using posix::stream_descriptor. It writes to /tmp/beastissue2221.out instead of the mock stream's internal buffer. The issue still occurs.
#include <boost/beast/http/serializer.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/string_body.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/http/write.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <cstdio>
#include <stdio.h>
int main(int, char**) {
boost::beast::http::response<boost::beast::http::string_body> response{boost::beast::http::status::ok, 11};
boost::beast::http::response_serializer<boost::beast::http::string_body> serializer{response};
boost::asio::io_context io_context{};
std::FILE* file{std::fopen("/tmp/beastissue2221.out", "w")};
boost::asio::posix::stream_descriptor stream{io_context.get_executor(), ::fileno(file)};
boost::beast::http::async_write_header(
stream, serializer,
[](boost::system::error_code, std::size_t) {
});
io_context.run();
boost::beast::http::response_serializer<boost::beast::http::string_body> serializer2{std::move(serializer)};
std::fclose(file);
}
This is great, thank you
This issue has been open for a while with no activity, has it been resolved?
I just re-tested the reproduction with latest commit on the develop branch (commit 30abfdb9) and the bug still occurs. Please de-stale
This issue has been open for a while with no activity, has it been resolved?
Tested with Beast commit a593738 and Boost version 1.78.0; issue still occurs.
Reproduced.
reproduced here for investigation: https://github.com/beast-issues/2221
why a separate organization called beast-issues?
It helps my mental filing cabinet
@madmongo1 what's the state of this?