https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81964

On Thu, 24 Aug 2017 11:55:58 +0300
Petr Ovtchenkov <p...@void-ptr.info> wrote:

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

Reply via email to