Fix flat_streambuf:

Don't call memcpy or memmove with null arguments.
This commit is contained in:
Vinnie Falco
2017-05-07 07:11:28 -07:00
parent 20c1ba78f1
commit df81d509d5
2 changed files with 25 additions and 8 deletions

View File

@ -3,6 +3,7 @@
* CMake hide command lines in .vcxproj Output windows" * CMake hide command lines in .vcxproj Output windows"
* Rename to detail::is_invocable * Rename to detail::is_invocable
* Rename project to http-bench * Rename project to http-bench
* Fix flat_streambuf
WebSocket: WebSocket:

View File

@ -193,12 +193,15 @@ prepare(std::size_t n) ->
{ {
if(n <= dist(out_, end_)) if(n <= dist(out_, end_))
{ {
// existing capacity is sufficient
last_ = out_ + n; last_ = out_ + n;
return{out_, n}; return{out_, n};
} }
auto const len = size(); auto const len = size();
if(n <= dist(p_, end_) - len) if(n <= capacity() - len)
{ {
// after a memmove,
// existing capacity is sufficient
if(len > 0) if(len > 0)
std::memmove(p_, in_, len); std::memmove(p_, in_, len);
in_ = p_; in_ = p_;
@ -206,17 +209,24 @@ prepare(std::size_t n) ->
last_ = out_ + n; last_ = out_ + n;
return {out_, n}; return {out_, n};
} }
// enforce maximum capacity
if(n > max_ - len) if(n > max_ - len)
throw std::length_error{ throw std::length_error{
"flat_streambuf overflow"}; "flat_streambuf overflow"};
// allocate a new buffer
auto const new_size = (std::min)(max_, auto const new_size = (std::min)(max_,
std::max<std::size_t>( std::max<std::size_t>(
detail::next_pow2(len + n), min_size)); detail::next_pow2(len + n), min_size));
auto const p = alloc_traits::allocate( auto const p = alloc_traits::allocate(
this->member(), new_size); this->member(), new_size);
std::memcpy(p, in_, len); if(len > 0)
alloc_traits::deallocate( {
this->member(), p_, dist(p_, end_)); BOOST_ASSERT(p);
BOOST_ASSERT(in_);
std::memcpy(p, in_, len);
alloc_traits::deallocate(
this->member(), p_, capacity());
}
p_ = p; p_ = p;
in_ = p_; in_ = p_;
out_ = in_ + len; out_ = in_ + len;
@ -244,7 +254,7 @@ void
basic_flat_streambuf<Allocator>:: basic_flat_streambuf<Allocator>::
reserve(std::size_t n) reserve(std::size_t n)
{ {
if(n <= dist(p_, end_)) if(n <= capacity())
return; return;
if(n > max_) if(n > max_)
throw std::length_error{ throw std::length_error{
@ -256,9 +266,13 @@ reserve(std::size_t n)
this->member(), new_size); this->member(), new_size);
auto const len = size(); auto const len = size();
if(len > 0) if(len > 0)
{
BOOST_ASSERT(p_);
BOOST_ASSERT(in_);
std::memcpy(p, in_, len); std::memcpy(p, in_, len);
alloc_traits::deallocate( alloc_traits::deallocate(
this->member(), p_, dist(p_, end_)); this->member(), p_, capacity());
}
p_ = p; p_ = p;
in_ = p_; in_ = p_;
out_ = p_ + len; out_ = p_ + len;
@ -272,11 +286,13 @@ basic_flat_streambuf<Allocator>::
shrink_to_fit() shrink_to_fit()
{ {
auto const len = size(); auto const len = size();
if(len == dist(p_, end_)) if(len == capacity())
return; return;
char* p; char* p;
if(len > 0) if(len > 0)
{ {
BOOST_ASSERT(p_);
BOOST_ASSERT(in_);
p = alloc_traits::allocate( p = alloc_traits::allocate(
this->member(), len); this->member(), len);
std::memcpy(p, in_, len); std::memcpy(p, in_, len);