Bug 96161 - istream::ignore sets eofbit too soon
Summary: istream::ignore sets eofbit too soon
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 10.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-10 21:10 UTC by Jonathan Wakely
Modified: 2026-04-29 03:42 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-07-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2020-07-10 21:10:45 UTC
#include <sstream>
#include <iostream>
int main()
{
  std::istringstream s("++");
  s.ignore(2, '-');
  std::cout << "EOF? " << s.eof() << std::endl;
}

This shows that we set eofbit when the end of the stream is reached, even though we have already discarded as many characters as requested.

Libc++ and MSVC do not set eofbit here.
Comment 1 GCC Commits 2020-07-13 11:26:35 UTC
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:ba8fe4b4832e30277f2e4a73b5d35b2e55074d07

commit r11-2054-gba8fe4b4832e30277f2e4a73b5d35b2e55074d07
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jul 13 10:26:39 2020 +0100

    libstdc++: Fix istream::ignore exit conditions (PR 94749, PR 96161)
    
    My previous fix for PR 94749 did fix the reported case, so that the next
    character is not discarded if it happens to equal the delimiter when __n
    characters have already been read. But it introduced a new bug, which is
    that the delimiter character would *not* be discarded if the number of
    characters discarded is numeric_limits<streamsize>::max() or more before
    reaching the delimiter.
    
    The new bug happens because I changed the code to check _M_gcount < __n.
    But when __n == numeric_limits<streamsize>::max() that is false, and so
    we don't discard the delimiter. It's not sufficient to check for the
    delimiter when the __large_ignore condition is true, because there's an
    edge case where the delimiter is reached when _M_gcount == __n and so
    we break out of the loop without setting __large_ignore.
    
    PR 96161 is a similar bug to the original PR 94749 report, where eofbit
    is set after discarding __n characters if there happen to be no more
    characters in the stream.
    
    This patch fixes both cases (and the regression) by checking different
    conditions for the __n == max case and the __n < max case. For the
    former case, we know that we must have either reached the delimiter or
    EOF, and the value of _M_gcount doesn't matter (except to avoid integer
    overflow). For the latter case we need to check _M_gcount first and only
    set eofbit or discard the delimiter if it didn't reach __n. For the
    latter case overflow can't happen because _M_gcount <= __n < max.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/94749
            PR libstdc++/96161
            * include/bits/istream.tcc (basic_istream::ignore(streamsize))
            [n == max]: Check overflow conditions on _M_gcount. Rely on
            the fact that either EOF or the delimiter was reached.
            [n < max]: Check _M_gcount < n before checking for EOF or
            delimiter.
            (basic_istream::ignore(streamsize, char_type): Likewise.
            * src/c++98/compatibility.cc (istream::ignore(streamsize))
            (wistream::ignore(streamsize)): Likewise.
            * src/c++98/istream.cc (istream::ignore(streamsize, char_type))
            (wistream::ignore(streamsize, char_type)): Likewise.
            * testsuite/27_io/basic_istream/ignore/char/94749.cc: Check that
            delimiter is discarded if the number of characters ignored
            doesn't fit in streamsize.
            * testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc:
            Likewise.
            * testsuite/27_io/basic_istream/ignore/char/96161.cc: New test.
            * testsuite/27_io/basic_istream/ignore/wchar_t/96161.cc: New test.
Comment 2 Jonathan Wakely 2020-07-13 11:33:30 UTC
Fixed on trunk so far.
Comment 3 Jonathan Wakely 2020-08-06 19:47:20 UTC
See also g:4e39f563c0cd25401f689c2093cb8c13692156ef