diff --git a/CHANGELOG.md b/CHANGELOG.md index cb7eb680..91ed0474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Version 47 * Disable operator<< for buffer_body * buffer_size overload for basic_multi_buffer::const_buffers_type +* Fix undefined behavior in pausation API Changes: diff --git a/include/beast/websocket/detail/pausation.hpp b/include/beast/websocket/detail/pausation.hpp index 728a057f..53a99884 100644 --- a/include/beast/websocket/detail/pausation.hpp +++ b/include/beast/websocket/detail/pausation.hpp @@ -30,7 +30,7 @@ class pausation base() = default; base(base &&) = default; virtual ~base() = default; - virtual void move(void* p) = 0; + virtual base* move(void* p) = 0; virtual void operator()() = 0; }; @@ -48,10 +48,10 @@ class pausation { } - void + base* move(void* p) override { - ::new(p) holder(std::move(*this)); + return ::new(p) holder(std::move(*this)); } void @@ -100,9 +100,7 @@ public: { if(other.base_) { - // type-pun - base_ = reinterpret_cast(&buf_[0]); - other.base_->move(buf_); + base_ = other.base_->move(buf_); other.base_ = nullptr; } } @@ -117,9 +115,7 @@ public: if(other.base_) { - // type-pun - base_ = reinterpret_cast(&buf_[0]); - other.base_->move(buf_); + base_ = other.base_->move(buf_); other.base_ = nullptr; } return *this; @@ -147,12 +143,11 @@ template void pausation::emplace(F&& f) { - static_assert(sizeof(buf_type) >= sizeof(holder), + using type = holder::type>; + static_assert(sizeof(buf_type) >= sizeof(type), "buffer too small"); BOOST_ASSERT(! base_); - ::new(buf_) holder(std::forward(f)); - // type-pun - base_ = reinterpret_cast(&buf_[0]); + base_ = ::new(buf_) type{std::forward(f)}; } } // detail diff --git a/include/beast/websocket/impl/close.ipp b/include/beast/websocket/impl/close.ipp index 6b748f20..e6ac1083 100644 --- a/include/beast/websocket/impl/close.ipp +++ b/include/beast/websocket/impl/close.ipp @@ -141,8 +141,7 @@ operator()(error_code ec, bool again) { // suspend d.state = 2; - d.ws.wr_op_.template emplace< - close_op>(std::move(*this)); + d.ws.wr_op_.emplace(std::move(*this)); return; } if(d.ws.failed_ || d.ws.wr_close_) diff --git a/include/beast/websocket/impl/ping.ipp b/include/beast/websocket/impl/ping.ipp index 905c9068..5083cb9e 100644 --- a/include/beast/websocket/impl/ping.ipp +++ b/include/beast/websocket/impl/ping.ipp @@ -139,8 +139,7 @@ operator()(error_code ec, bool again) { // suspend d.state = 2; - d.ws.ping_op_.template emplace< - ping_op>(std::move(*this)); + d.ws.ping_op_.emplace(std::move(*this)); return; } if(d.ws.failed_ || d.ws.wr_close_) diff --git a/include/beast/websocket/impl/read.ipp b/include/beast/websocket/impl/read.ipp index 02af9f24..1aab6931 100644 --- a/include/beast/websocket/impl/read.ipp +++ b/include/beast/websocket/impl/read.ipp @@ -456,8 +456,7 @@ operator()(error_code ec, // suspend d.state = do_pong_resume; BOOST_ASSERT(d.ws.wr_block_ != &d); - d.ws.rd_op_.template emplace< - read_frame_op>(std::move(*this)); + d.ws.rd_op_.emplace(std::move(*this)); return; } d.state = do_pong; @@ -496,8 +495,7 @@ operator()(error_code ec, { // suspend d.state = do_close_resume; - d.ws.rd_op_.template emplace< - read_frame_op>(std::move(*this)); + d.ws.rd_op_.emplace(std::move(*this)); return; } d.state = do_close; @@ -630,8 +628,7 @@ operator()(error_code ec, { // suspend d.state = do_fail + 2; - d.ws.rd_op_.template emplace< - read_frame_op>(std::move(*this)); + d.ws.rd_op_.emplace(std::move(*this)); return; } // fall through diff --git a/include/beast/websocket/impl/write.ipp b/include/beast/websocket/impl/write.ipp index 0f94fc66..2172eee8 100644 --- a/include/beast/websocket/impl/write.ipp +++ b/include/beast/websocket/impl/write.ipp @@ -491,8 +491,7 @@ operator()(error_code ec, { // suspend d.state = do_maybe_suspend + 1; - d.ws.wr_op_.template emplace< - write_frame_op>(std::move(*this)); + d.ws.wr_op_.emplace(std::move(*this)); return; } if(d.ws.failed_ || d.ws.wr_close_)