[PATCH] istream_iterator: unexpected read in ctor
Petr Ovtchenkov
ptr@void-ptr.info
Thu Aug 24 11:38:00 GMT 2017
istream_iterator do unexpected read from stream
when initialized by istream&.
It is not required from increment operators of istream_iterator
that _M_ok will be true as precondition.
---
libstdc++-v3/include/bits/stream_iterator.h | 19 +++++-----
.../24_iterators/istream_iterator/81964.cc | 42 ++++++++++++++++++++++
2 files changed, 50 insertions(+), 11 deletions(-)
create mode 100644 libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc
diff --git a/libstdc++-v3/include/bits/stream_iterator.h b/libstdc++-v3/include/bits/stream_iterator.h
index f9c6ba6..26959ce 100644
--- a/libstdc++-v3/include/bits/stream_iterator.h
+++ b/libstdc++-v3/include/bits/stream_iterator.h
@@ -56,8 +56,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
istream_type* _M_stream;
- _Tp _M_value;
- bool _M_ok;
+ mutable _Tp _M_value;
+ mutable bool _M_ok;
public:
/// Construct end of input stream iterator.
@@ -66,8 +66,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Construct start of input stream iterator.
istream_iterator(istream_type& __s)
- : _M_stream(&__s)
- { _M_read(); }
+ : _M_stream(&__s), _M_value(), _M_ok(false)
+ { }
istream_iterator(const istream_iterator& __obj)
: _M_stream(__obj._M_stream), _M_value(__obj._M_value),
@@ -77,6 +77,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _Tp&
operator*() const
{
+ if (!_M_ok) {
+ _M_read();
+ }
__glibcxx_requires_cond(_M_ok,
_M_message(__gnu_debug::__msg_deref_istream)
._M_iterator(*this));
@@ -89,9 +92,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
istream_iterator&
operator++()
{
- __glibcxx_requires_cond(_M_ok,
- _M_message(__gnu_debug::__msg_inc_istream)
- ._M_iterator(*this));
_M_read();
return *this;
}
@@ -99,9 +99,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
istream_iterator
operator++(int)
{
- __glibcxx_requires_cond(_M_ok,
- _M_message(__gnu_debug::__msg_inc_istream)
- ._M_iterator(*this));
istream_iterator __tmp = *this;
_M_read();
return __tmp;
@@ -113,7 +110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
void
- _M_read()
+ _M_read() const
{
_M_ok = (_M_stream && *_M_stream) ? true : false;
if (_M_ok)
diff --git a/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc b/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc
new file mode 100644
index 0000000..f58fc87
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+// libstdc++/81964
+void test0x()
+{
+ using namespace std;
+ bool test __attribute__((unused)) = true;
+
+ std::istringstream s("1 2");
+ std::istream_iterator<int> ii1(s);
+ std::istream_iterator<int> ii2(s);
+
+ VERIFY( *ii2 == 1 );
+ VERIFY( *ii1 == 2 );
+}
+
+int main()
+{
+ test0x();
+ return 0;
+}
--
2.10.1
More information about the Gcc-patches
mailing list