Fix ostream prepare calculation for low limits:

This resolves an issue where the ostream could try to
exceeed the configured maximum size of a dynamic buffer
when the maximum is set to a very low number.
This commit is contained in:
Vinnie Falco
2018-12-15 18:11:29 -08:00
parent b367776c37
commit 81e3642fa7
2 changed files with 28 additions and 21 deletions

View File

@ -13,6 +13,7 @@ Version 200
* Optimize for size on buffers_cat preconditions * Optimize for size on buffers_cat preconditions
* Refactor buffers_suffix * Refactor buffers_suffix
* Tidy up flat_buffer tests * Tidy up flat_buffer tests
* Fix ostream prepare calculation for low limits
API Changes: API Changes:

View File

@ -83,9 +83,7 @@ class ostream_buffer
using traits_type = typename using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type; std::basic_streambuf<CharT, Traits>::traits_type;
static std::size_t constexpr max_size = 512; DynamicBuffer& b_;
DynamicBuffer& buf_;
public: public:
ostream_buffer(ostream_buffer&&) = default; ostream_buffer(ostream_buffer&&) = default;
@ -97,8 +95,8 @@ public:
} }
explicit explicit
ostream_buffer(DynamicBuffer& buf) ostream_buffer(DynamicBuffer& b)
: buf_(buf) : b_(b)
{ {
prepare(); prepare();
} }
@ -130,8 +128,13 @@ private:
void void
prepare() prepare()
{ {
auto bs = buf_.prepare( static std::size_t constexpr max_size = 65536;
read_size_or_throw(buf_, max_size)); auto const max_prepare = std::min<std::size_t>(
std::max<std::size_t>(
512, b_.capacity() - b_.size()),
std::min<std::size_t>(
max_size, b_.max_size() - b_.size()));
auto const bs = b_.prepare(max_prepare);
auto const b = buffers_front(bs); auto const b = buffers_front(bs);
auto const p = static_cast<CharT*>(b.data()); auto const p = static_cast<CharT*>(b.data());
this->setp(p, this->setp(p,
@ -141,7 +144,7 @@ private:
void void
flush(int extra = 0) flush(int extra = 0)
{ {
buf_.commit( b_.commit(
(this->pptr() - this->pbase() + extra) * (this->pptr() - this->pbase() + extra) *
sizeof(CharT)); sizeof(CharT));
} }
@ -162,9 +165,7 @@ class ostream_buffer
using traits_type = typename using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type; std::basic_streambuf<CharT, Traits>::traits_type;
static std::size_t constexpr max_size = 512; DynamicBuffer& b_;
DynamicBuffer& buf_;
public: public:
ostream_buffer(ostream_buffer&&) = delete; ostream_buffer(ostream_buffer&&) = delete;
@ -176,8 +177,8 @@ public:
} }
explicit explicit
ostream_buffer(DynamicBuffer& buf) ostream_buffer(DynamicBuffer& b)
: buf_(buf) : b_(b)
{ {
prepare(); prepare();
} }
@ -209,8 +210,13 @@ private:
void void
prepare() prepare()
{ {
auto bs = buf_.prepare( static std::size_t constexpr max_size = 65536;
read_size_or_throw(buf_, max_size)); auto const max_prepare = std::min<std::size_t>(
std::max<std::size_t>(
512, b_.capacity() - b_.size()),
std::min<std::size_t>(
max_size, b_.max_size() - b_.size()));
auto const bs = b_.prepare(max_prepare);
auto const b = buffers_front(bs); auto const b = buffers_front(bs);
auto const p = static_cast<CharT*>(b.data()); auto const p = static_cast<CharT*>(b.data());
this->setp(p, this->setp(p,
@ -220,7 +226,7 @@ private:
void void
flush(int extra = 0) flush(int extra = 0)
{ {
buf_.commit( b_.commit(
(this->pptr() - this->pbase() + extra) * (this->pptr() - this->pbase() + extra) *
sizeof(CharT)); sizeof(CharT));
} }
@ -242,17 +248,17 @@ class ostream_helper<
public: public:
explicit explicit
ostream_helper(DynamicBuffer& buf); ostream_helper(DynamicBuffer& b);
ostream_helper(ostream_helper&& other); ostream_helper(ostream_helper&& other);
}; };
template<class DynamicBuffer, class CharT, class Traits> template<class DynamicBuffer, class CharT, class Traits>
ostream_helper<DynamicBuffer, CharT, Traits, true>:: ostream_helper<DynamicBuffer, CharT, Traits, true>::
ostream_helper(DynamicBuffer& buf) ostream_helper(DynamicBuffer& b)
: std::basic_ostream<CharT, Traits>( : std::basic_ostream<CharT, Traits>(
&this->osb_) &this->osb_)
, osb_(buf) , osb_(b)
{ {
} }
@ -293,11 +299,11 @@ class ostream_helper<
{ {
public: public:
explicit explicit
ostream_helper(DynamicBuffer& buf) ostream_helper(DynamicBuffer& b)
: ostream_helper_base<ostream_buffer< : ostream_helper_base<ostream_buffer<
DynamicBuffer, CharT, Traits, false>>( DynamicBuffer, CharT, Traits, false>>(
new ostream_buffer<DynamicBuffer, new ostream_buffer<DynamicBuffer,
CharT, Traits, false>(buf)) CharT, Traits, false>(b))
, std::basic_ostream<CharT, Traits>(this->member.get()) , std::basic_ostream<CharT, Traits>(this->member.get())
{ {
} }