Title
istream::gcount() can overflow
Status
c++23
Section
[istream.unformatted]
Submitter
Jonathan Wakely

Created on 2020-07-10.00:00:00 last changed 13 months ago

Messages

Date: 2020-11-09.20:31:48

Proposed resolution:

This wording is relative to N4861.

  1. Modify [istream.unformatted] as indicated:

    streamsize gcount() const;
    

    -2- Effects: None. This member function does not behave as an unformatted input function (as described above).

    -3- Returns: The number of characters extracted by the last unformatted input member function called for the object. If the number cannot be represented, returns numeric_limits<streamsize>::max().

Date: 2020-11-09.00:00:00

[ 2020-11-09 Approved In November virtual meeting. Status changed: Ready → WP. ]

Date: 2020-07-15.00:00:00

[ 2020-07-17; Moved to Ready in telecon ]

On the reflector Davis pointed out that there are other members which can cause gcount() to overflow. There was unanimous agreement on the reflector and the telecon that Option A is better.

Date: 2020-07-17.23:03:18

The standard doesn't say what gcount() should return if the last unformatted input operation extracted more than numeric_limits<streamsize>::max() characters. This is possible when using istream::ignore(numeric_limits<streamsize>::max(), delim), which will keep extracting characters until the delimiter is found. On a 32-bit platform files larger than 2GB can overflow the counter, so can a streambuf reading from a network socket, or producing random characters.

Libstdc++ saturates the counter in istream::ignore, so that gcount() returns numeric_limits<streamsize>::max(). Libc++ results in an integer overflow.

As far as I'm aware, only istream::ignore can extract more than numeric_limits<streamsize>::max() characters at once. We could either fix it in the specification of ignore, or in gcount.

Previous resolution [SUPERSEDED]:

This wording is relative to N4861.

Option A:
  1. Modify [istream.unformatted] as indicated:

    streamsize gcount() const;
    

    -2- Effects: None. This member function does not behave as an unformatted input function (as described above).

    -3- Returns: The number of characters extracted by the last unformatted input member function called for the object. If the number cannot be represented, returns numeric_limits<streamsize>::max().

Option B:
  1. Modify [istream.unformatted] as indicated:

    basic_istream<charT, traits>& ignore(streamsize n = 1, int_type delim = traits::eof());
    

    -25- Effects: Behaves as an unformatted input function (as described above). After constructing a sentry object, extracts characters and discards them. Characters are extracted until any of the following occurs:

    1. (25.1) — n != numeric_limits<streamsize>::max() ([numeric.limits]) and n characters have been extracted so far

    2. (25.2) — end-of-file occurs on the input sequence (in which case the function calls setstate(eofbit), which may throw ios_base::failure ([iostate.flags]));

    3. (25.3) — traits::eq_int_type(traits::to_int_type(c), delim) for the next available input character c (in which case c is extracted).

    -?- If the number of characters extracted is greater than numeric_limits<streamsize>::max() then for the purposes of gcount() the number is treated as numeric_limits<streamsize>::max().

    -26- Remarks: The last condition will never occur if traits::eq_int_type(delim, traits::eof()).

    -27- Returns: *this.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2020-11-09 20:31:48adminsetmessages: + msg11550
2020-11-09 20:31:48adminsetstatus: ready -> wp
2020-07-17 22:37:26adminsetmessages: + msg11397
2020-07-17 22:37:26adminsetstatus: new -> ready
2020-07-12 17:21:41adminsetmessages: + msg11368
2020-07-10 00:00:00admincreate