chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.94k stars 1.22k forks source link

Supply a buffer type to asio::buffer() produces invalid new buffer #1197

Open timpavlic opened 1 year ago

timpavlic commented 1 year ago

Some heavily templated code I have has been inadvertently calling asio::buffer(x), where x is the result of a previous call to asio::buffer.

Having updated from 1.20 to 1.24 (actually boost 1.77 to .180), I suspect it's due to this new feature in the 1.24 revision history:

Added buffer() overloads for contiguous containers, such as std::span.

Debugging through, it looks like one of these new overloads is now picking up the address of the buffer, and multiplying the size of the buffer by the number of elements in the buffer.

I would expect the result of asio::buffer(asio::buffer(x)) to essentially be performing a copy construction of whatever the first result was.

#include <boost/asio.hpp>
#include <cstdio>

int main() {

  const std::array<char, 20> raw{};
  const auto buff1 = boost::asio::buffer(raw);
  const auto buff2 = boost::asio::buffer(buff1);

  ::printf("Raw lives @ %p\n", &raw[0]);
  ::printf("buff1 data @ %p    size: %zu\n", buff1.data(), buff1.size());
  ::printf("buff2 data @ %p    size: %zu\n", buff2.data(), buff2.size());

  constexpr auto size = sizeof(decltype(buff1));
  ::printf("\nsizeof decltype(buff1): %zu\n", size);
  ::printf("%zu * sizeof == %zu\n", buff1.size(), buff1.size() * size);

  ::printf("buff1 lives @ %p\n", &buff1);
  ::printf("buff2.data() == &buff1 ? %s\n", (buff2.data() == &buff1) ? "yes" : "no");
  ::printf("buff2.size() == %zu * sizeof ? %s\n", buff1.size(), (buff2.size() == buff1.size() * size) ? "yes" : "no");
}