beast icon indicating copy to clipboard operation
beast copied to clipboard

Assertion failure "Incrementing a default-constructed iterator" when moving http::response_serializer

Open ednolan opened this issue 4 years ago • 11 comments
trafficstars

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

ednolan avatar Apr 24 '21 19:04 ednolan

Are you sure your mock stream stream is correct? Have you tried it with a simple asio composed write?

madmongo1 avatar Apr 24 '21 20:04 madmongo1

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);
}

ednolan avatar Apr 26 '21 14:04 ednolan

This is great, thank you

madmongo1 avatar Apr 26 '21 15:04 madmongo1

This issue has been open for a while with no activity, has it been resolved?

stale[bot] avatar May 29 '21 16:05 stale[bot]

I just re-tested the reproduction with latest commit on the develop branch (commit 30abfdb9) and the bug still occurs. Please de-stale

ednolan avatar Jun 03 '21 18:06 ednolan

This issue has been open for a while with no activity, has it been resolved?

stale[bot] avatar Jan 09 '22 04:01 stale[bot]

Tested with Beast commit a593738 and Boost version 1.78.0; issue still occurs.

ednolan avatar Jan 10 '22 04:01 ednolan

Reproduced.

madmongo1 avatar Jan 30 '22 18:01 madmongo1

reproduced here for investigation: https://github.com/beast-issues/2221

madmongo1 avatar Jan 31 '22 07:01 madmongo1

why a separate organization called beast-issues?

vinniefalco avatar Jan 31 '22 17:01 vinniefalco

It helps my mental filing cabinet

madmongo1 avatar Feb 01 '22 06:02 madmongo1

@madmongo1 what's the state of this?

klemens-morgenstern avatar Sep 24 '22 05:09 klemens-morgenstern