boostorg / core

Boost Core Utilities
132 stars 87 forks source link

`boost::swap` accepts const objects which causes run-time crashes #43

Closed akrzemi1 closed 5 years ago

akrzemi1 commented 5 years ago

Consider the following code. This reproduces the situation from boost::optional (see issue #63) which relies on boost::swap.

#include <boost/core/swap.hpp>

namespace boost {

template <typename T>
struct Wrapper
{
  T value;
};

template <typename T>
inline void swap (Wrapper<T> & w, Wrapper<T> & v)
{
  boost::swap(w, v);
}

} // namespace boost

int main()
{
  const boost::Wrapper<int> w {2};
  const boost::Wrapper<int> v {3};
  swap(w, v); // segmentation fault
}

The swap in the last line compiles, because the signature in boost::swap accepts references to const. I am not sure what happens next, but this is probably an infinite recursion.

Note that std::swap does not have this problem, because it is constrained (T shall be move constructible and move assignable).

pdimov commented 5 years ago

With what compiler does this compile?

pdimov commented 5 years ago

Ah, I see. When std::swap is constrained.

Lastique commented 5 years ago

We could probably use a compile-fail test. The one in the description works as one.

pdimov commented 5 years ago

https://github.com/boostorg/core/commit/e9f986d11e046572aaf138f330c29f26182f794c

akrzemi1 commented 5 years ago

Thanks for the express fix.