Fix undefined behavior in pausation

This commit is contained in:
Vinnie Falco
2017-06-02 20:50:11 -07:00
parent 02d5aedc29
commit a38a9adbe1
6 changed files with 15 additions and 25 deletions

View File

@ -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:

View File

@ -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<base*>(&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<base*>(&buf_[0]);
other.base_->move(buf_);
base_ = other.base_->move(buf_);
other.base_ = nullptr;
}
return *this;
@ -147,12 +143,11 @@ template<class F>
void
pausation::emplace(F&& f)
{
static_assert(sizeof(buf_type) >= sizeof(holder<F>),
using type = holder<typename std::decay<F>::type>;
static_assert(sizeof(buf_type) >= sizeof(type),
"buffer too small");
BOOST_ASSERT(! base_);
::new(buf_) holder<F>(std::forward<F>(f));
// type-pun
base_ = reinterpret_cast<base*>(&buf_[0]);
base_ = ::new(buf_) type{std::forward<F>(f)};
}
} // detail

View File

@ -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_)

View File

@ -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_)

View File

@ -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

View File

@ -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_)