Fix streambuf bug:

The buffers_type::iterator could hold a pointer to a buffers_type that
was destroyed. This changes buffers_type::iterator to point to the
original streambuf instead, which always outlives the iterator.
This commit is contained in:
Vinnie Falco
2015-02-12 12:36:18 -08:00
committed by Tom Ritchford
parent 7aa6b6b21d
commit 9bbcbd546b

View File

@@ -231,16 +231,13 @@ private:
using argument_type = element; using argument_type = element;
using result_type = value_type; using result_type = value_type;
const_buffers_type const* buffers_; basic_streambuf const* streambuf_ = nullptr;
transform() transform() = default;
: buffers_ (nullptr)
{
}
explicit explicit
transform (const_buffers_type const& buffers) transform (basic_streambuf const& streambuf)
: buffers_ (&buffers) : streambuf_ (&streambuf)
{ {
} }
@@ -255,11 +252,15 @@ public:
transform, typename list_type::const_iterator, transform, typename list_type::const_iterator,
value_type, value_type>; value_type, value_type>;
const_buffers_type() = default;
const_buffers_type (const_buffers_type const&) = default;
const_buffers_type& operator= (const_buffers_type const&) = default;
const_iterator const_iterator
begin() const begin() const
{ {
return const_iterator (streambuf_->list_.begin(), return const_iterator (streambuf_->list_.begin(),
transform(*this)); transform(*streambuf_));
} }
const_iterator const_iterator
@@ -267,7 +268,7 @@ public:
{ {
return const_iterator (streambuf_->out_ == return const_iterator (streambuf_->out_ ==
streambuf_->list_.end() ? streambuf_->list_.end() : streambuf_->list_.end() ? streambuf_->list_.end() :
std::next(streambuf_->out_), transform(*this)); std::next(streambuf_->out_), transform(*streambuf_));
} }
private: private:
@@ -290,12 +291,11 @@ basic_streambuf<Allocator>::const_buffers_type::
transform::operator() (element const& e) const -> transform::operator() (element const& e) const ->
value_type const value_type const
{ {
basic_streambuf const& streambuf = *buffers_->streambuf_;
return value_type (e.data(), return value_type (e.data(),
(streambuf.out_ == streambuf.list_.end() || (streambuf_->out_ == streambuf_->list_.end() ||
&e != &*streambuf.out_) ? e.size() : streambuf.out_pos_) + &e != &*streambuf_->out_) ? e.size() : streambuf_->out_pos_) +
(&e == &*streambuf.list_.begin() ? (&e == &*streambuf_->list_.begin() ?
streambuf.in_pos_ : 0); streambuf_->in_pos_ : 0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -312,16 +312,13 @@ private:
using argument_type = element; using argument_type = element;
using result_type = value_type; using result_type = value_type;
mutable_buffers_type const* buffers_; basic_streambuf const* streambuf_ = nullptr;
transform() transform() = default;
: buffers_ (nullptr)
{
}
explicit explicit
transform (mutable_buffers_type const& buffers) transform (basic_streambuf const& streambuf)
: buffers_ (&buffers) : streambuf_ (&streambuf)
{ {
} }
@@ -336,18 +333,22 @@ public:
transform, typename list_type::const_iterator, transform, typename list_type::const_iterator,
value_type, value_type>; value_type, value_type>;
mutable_buffers_type() = default;
mutable_buffers_type (mutable_buffers_type const&) = default;
mutable_buffers_type& operator= (mutable_buffers_type const&) = default;
const_iterator const_iterator
begin() const begin() const
{ {
return const_iterator (streambuf_->out_, return const_iterator (streambuf_->out_,
transform(*this)); transform(*streambuf_));
} }
const_iterator const_iterator
end() const end() const
{ {
return const_iterator (streambuf_->list_.end(), return const_iterator (streambuf_->list_.end(),
transform(*this)); transform(*streambuf_));
} }
private: private:
@@ -368,10 +369,9 @@ basic_streambuf<Allocator>::mutable_buffers_type::
transform::operator() (element const& e) const -> transform::operator() (element const& e) const ->
value_type const value_type const
{ {
basic_streambuf const& streambuf = *buffers_->streambuf_; return value_type (e.data(), &e == &*std::prev(streambuf_->list_.end()) ?
return value_type (e.data(), &e == &*std::prev(streambuf.list_.end()) ? streambuf_->out_end_ : e.size()) + (&e == &*streambuf_->out_ ?
streambuf.out_end_ : e.size()) + (&e == &*streambuf.out_ ? streambuf_->out_pos_ : 0);
streambuf.out_pos_ : 0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------