public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Ian Lance Taylor <ian@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc/devel/gccgo] libstdc++: Fix istream::ignore discarding too many chars (PR 94749) Date: Sun, 12 Jul 2020 19:28:15 +0000 (GMT) [thread overview] Message-ID: <20200712192815.8516E388C01F@sourceware.org> (raw) https://gcc.gnu.org/g:b32eea9c0c25a03e77170675abc4e4bcab6d2b3b commit b32eea9c0c25a03e77170675abc4e4bcab6d2b3b Author: Jonathan Wakely <jwakely@redhat.com> Date: Thu Jun 11 18:41:37 2020 +0100 libstdc++: Fix istream::ignore discarding too many chars (PR 94749) The current code assumes that if the next character in the stream is equal to the delimiter then we stopped because we saw that delimiter, and so discards it. But in the testcase for the PR we stop because we reached the maximum number of characters, and it's coincidence that the next character equals the delimiter. We should not discard the next character in that case. The fix is to check that we haven't discarded __n characters already, instead of checking whether the next character equals __delim. Because we've already checked for EOF, if we haven't discarded __n yet then we know we stopped because we saw the delimiter. On the other hand, if the next character is the delimiter we don't know if that's why we stopped. PR libstdc++/94749 * include/bits/istream.tcc (basic_istream::ignore(streamsize, CharT)): Only discard an extra character if we didn't already reach the maximum number. * src/c++98/istream.cc (istream::ignore(streamsiz, char)) (wistream::ignore(streamsize, wchar_t)): Likewise. * testsuite/27_io/basic_istream/ignore/char/94749.cc: New test. * testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc: New test. Diff: --- libstdc++-v3/include/bits/istream.tcc | 6 +- libstdc++-v3/src/c++98/istream.cc | 12 ++-- .../27_io/basic_istream/ignore/char/94749.cc | 76 ++++++++++++++++++++++ .../27_io/basic_istream/ignore/wchar_t/94749.cc | 76 ++++++++++++++++++++++ 4 files changed, 158 insertions(+), 12 deletions(-) diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index c82da56b9f9..d36374c707f 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -601,11 +601,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (traits_type::eq_int_type(__c, __eof)) __err |= ios_base::eofbit; - else if (traits_type::eq_int_type(__c, __delim)) + else if (_M_gcount < __n) // implies __c == __delim { - if (_M_gcount - < __gnu_cxx::__numeric_traits<streamsize>::__max) - ++_M_gcount; + ++_M_gcount; __sb->sbumpc(); } } diff --git a/libstdc++-v3/src/c++98/istream.cc b/libstdc++-v3/src/c++98/istream.cc index 79d829e23b4..d6fee1a0d66 100644 --- a/libstdc++-v3/src/c++98/istream.cc +++ b/libstdc++-v3/src/c++98/istream.cc @@ -171,11 +171,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (traits_type::eq_int_type(__c, __eof)) __err |= ios_base::eofbit; - else if (traits_type::eq_int_type(__c, __delim)) + else if (_M_gcount < __n) // implies __c == __delim { - if (_M_gcount - < __gnu_cxx::__numeric_traits<streamsize>::__max) - ++_M_gcount; + ++_M_gcount; __sb->sbumpc(); } } @@ -413,11 +411,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (traits_type::eq_int_type(__c, __eof)) __err |= ios_base::eofbit; - else if (traits_type::eq_int_type(__c, __delim)) + else if (_M_gcount < __n) // implies __c == __delim { - if (_M_gcount - < __gnu_cxx::__numeric_traits<streamsize>::__max) - ++_M_gcount; + ++_M_gcount; __sb->sbumpc(); } } diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/char/94749.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/char/94749.cc new file mode 100644 index 00000000000..03b5286b00e --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/char/94749.cc @@ -0,0 +1,76 @@ +// 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 } + +// PR libstdc++/94749 +// basic_istream::ignore(n, c) discards n+1 if next character is equal to c. + +#include <sstream> +#include <testsuite_hooks.h> + +typedef char C; + +void +test01() +{ + std::basic_istringstream<C> s(" + -"); + s.ignore(1, '+'); + VERIFY( s.get() == '+' ); + s.ignore(3, '-'); + VERIFY( s.get() == '-' ); +} + +void +test02() +{ + std::basic_istringstream<C> s(".+...-"); + s.ignore(1, '+'); + VERIFY( s.get() == '+' ); + s.ignore(3, '-'); + VERIFY( s.get() == '-' ); +} + +void +test03() +{ + std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(" + -"); + s.ignore(1, '+'); + VERIFY( s.get() == '+' ); + s.ignore(3, '-'); + VERIFY( s.get() == '-' ); +} + +void +test04() +{ + std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(".+...-"); + s.ignore(1, '+'); + VERIFY( s.get() == '+' ); + s.ignore(3, '-'); + VERIFY( s.get() == '-' ); +} + + +int +main() +{ + test01(); + test02(); + test03(); + test04(); +} diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc new file mode 100644 index 00000000000..e5ec4e7d697 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc @@ -0,0 +1,76 @@ +// 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 } + +// PR libstdc++/94749 +// basic_istream::ignore(n, c) discards n+1 if next character is equal to c. + +#include <sstream> +#include <testsuite_hooks.h> + +typedef wchar_t C; + +void +test01() +{ + std::basic_istringstream<C> s(L" + -"); + s.ignore(1, L'+'); + VERIFY( s.get() == L'+' ); + s.ignore(3, L'-'); + VERIFY( s.get() == L'-' ); +} + +void +test02() +{ + std::basic_istringstream<C> s(L".+...-"); + s.ignore(1, L'+'); + VERIFY( s.get() == L'+' ); + s.ignore(3, L'-'); + VERIFY( s.get() == L'-' ); +} + +void +test03() +{ + std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(L" + -"); + s.ignore(1, L'+'); + VERIFY( s.get() == L'+' ); + s.ignore(3, L'-'); + VERIFY( s.get() == L'-' ); +} + +void +test04() +{ + std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(L".+...-"); + s.ignore(1, L'+'); + VERIFY( s.get() == L'+' ); + s.ignore(3, L'-'); + VERIFY( s.get() == L'-' ); +} + + +int +main() +{ + // test01(); + // test02(); + test03(); + test04(); +}
reply other threads:[~2020-07-12 19:28 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200712192815.8516E388C01F@sourceware.org \ --to=ian@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).