__streambuf_type* __this_sb = this->rdbuf();
int_type __c = __this_sb->sgetc();
char_type __c2 = traits_type::to_char_type(__c);
+ unsigned long long __gcount = 0;
while (!traits_type::eq_int_type(__c, __eof)
&& !traits_type::eq_int_type(__c, __idelim)
&& !traits_type::eq_int_type(__sb.sputc(__c2), __eof))
{
- ++_M_gcount;
+ ++__gcount;
__c = __this_sb->snextc();
__c2 = traits_type::to_char_type(__c);
}
if (traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3464. istream::gcount() can overflow
+ if (__gcount <= __gnu_cxx::__numeric_traits<streamsize>::__max)
+ _M_gcount = __gcount;
+ else
+ _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max;
}
__catch(__cxxabiv1::__forced_unwind&)
{
--- /dev/null
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target { ! lp64 } } }
+
+#include <istream>
+#include <streambuf>
+#include <limits>
+#include <testsuite_hooks.h>
+
+typedef char C;
+
+struct buff : std::basic_streambuf<C>
+{
+ typedef std::streamsize streamsize;
+ typedef std::numeric_limits<streamsize> limits;
+
+ buff() : count(0), buf() { }
+
+ int_type underflow()
+ {
+ // Number of characters left until we overflow the counter
+ const streamsize headroom = limits::max() - count;
+
+ if (headroom == 0)
+ return traits_type::eof();
+
+ if (bufsz < headroom)
+ count += bufsz;
+ else
+ count = limits::max();
+
+ this->setg(buf + 1, buf + 1, buf + bufsz);
+
+ return buf[0];
+ }
+
+ int_type overflow(int_type c)
+ {
+ if (traits_type::eq_int_type(c , traits_type::eof()))
+ return c;
+ this->setp(buf, buf + bufsz - 1);
+ return traits_type::not_eof(c);
+ }
+
+ streamsize count;
+
+ static const streamsize bufsz = (2048 << limits::digits10) + 1;
+ char_type buf[bufsz];
+};
+
+void
+test01()
+{
+ // Not possible to overflow 64-bit streamsize in reasonable time.
+ if (std::numeric_limits<std::streamsize>::digits > 32)
+ return;
+
+ std::basic_istream<C> in(new buff);
+ buff out;
+ in.get(out);
+ VERIFY( in.gcount() == std::numeric_limits<std::streamsize>::max() );
+
+ delete in.rdbuf(new buff);
+
+ in.get();
+ VERIFY( in.gcount() == 1 );
+
+ in.get(out, 'a');
+ VERIFY( in.gcount() == std::numeric_limits<std::streamsize>::max() );
+}
+
+int
+main()
+{
+ test01();
+}
--- /dev/null
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target { ! lp64 } } }
+
+#include <istream>
+#include <streambuf>
+#include <limits>
+#include <testsuite_hooks.h>
+
+typedef wchar_t C;
+
+struct buff : std::basic_streambuf<C>
+{
+ typedef std::streamsize streamsize;
+ typedef std::numeric_limits<streamsize> limits;
+
+ buff() : count(0), buf() { }
+
+ int_type underflow()
+ {
+ // Number of characters left until we overflow the counter
+ const streamsize headroom = limits::max() - count;
+
+ if (headroom == 0)
+ return traits_type::eof();
+
+ if (bufsz < headroom)
+ count += bufsz;
+ else
+ count = limits::max();
+
+ this->setg(buf + 1, buf + 1, buf + bufsz);
+
+ return buf[0];
+ }
+
+ int_type overflow(int_type c)
+ {
+ if (traits_type::eq_int_type(c , traits_type::eof()))
+ return c;
+ this->setp(buf, buf + bufsz - 1);
+ return traits_type::not_eof(c);
+ }
+
+ streamsize count;
+
+ static const streamsize bufsz = (2048 << limits::digits10) + 1;
+ char_type buf[bufsz];
+};
+
+void
+test01()
+{
+ // Not possible to overflow 64-bit streamsize in reasonable time.
+ if (std::numeric_limits<std::streamsize>::digits > 32)
+ return;
+
+ std::basic_istream<C> in(new buff);
+ buff out;
+ in.get(out);
+ VERIFY( in.gcount() == std::numeric_limits<std::streamsize>::max() );
+
+ delete in.rdbuf(new buff);
+
+ in.get();
+ VERIFY( in.gcount() == 1 );
+
+ in.get(out, 'a');
+ VERIFY( in.gcount() == std::numeric_limits<std::streamsize>::max() );
+}
+
+int
+main()
+{
+ test01();
+}