[Bug libstdc++/106248] [11/12 Regression] operator>>std::basic_istream at boundary condition behave differently in different opt levels

2022-08-03 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106248

--- Comment #10 from CVS Commits  ---
The releases/gcc-12 branch has been updated by Jonathan Wakely
:

https://gcc.gnu.org/g:7a0ed28d4feb450f1ede5b52b57793a5df5b19fe

commit r12-8659-g7a0ed28d4feb450f1ede5b52b57793a5df5b19fe
Author: Jonathan Wakely 
Date:   Tue Jul 12 11:18:47 2022 +0100

libstdc++: Check for EOF if extraction avoids buffer overflow [PR106248]

In r11-2581-g17abcc77341584 (for LWG 2499) I added overflow checks to
the pre-C++20 operator>>(istream&, char*) overload.  Those checks can
cause extraction to stop after filling the buffer, where previously it
would have tried to extract another character and stopped at EOF. When
that happens we no longer set eofbit in the stream state, which is
consistent with the behaviour of the new C++20 overload, but is an
observable and unexpected change in the C++17 behaviour. What makes it
worse is that the behaviour change is dependent on optimization, because
__builtin_object_size is used to detect the buffer size and that only
works when optimizing.

To avoid the unexpected and optimization-dependent change in behaviour,
set eofbit manually if we stopped extracting because of the buffer size
check, but had reached EOF anyway. If the stream's rdstate() != goodbit
or width() is non-zero and smaller than the buffer, there's nothing to
do. Otherwise, we filled the buffer and need to check for EOF, and maybe
set eofbit.

The new check is guarded by #ifdef __OPTIMIZE__ because otherwise
__builtin_object_size is useless. There's no point compiling and
emitting dead code that can't be eliminated because we're not
optimizing.

We could add extra checks that the next character in the buffer is not
whitespace, to detect the case where we stopped early and prevented a
buffer overflow that would have happened otherwise. That would allow us
to assert or set badbit in the stream state when undefined behaviour was
prevented. However, those extra checks would increase the size of the
function, potentially reducing the likelihood of it being inlined, and
so making the buffer size detection less reliable. It seems preferable
to prevent UB and silently truncate, rather than miss the UB and allow
the overflow to happen.

libstdc++-v3/ChangeLog:

PR libstdc++/106248
* include/std/istream [C++17] (operator>>(istream&, char*)):
Set eofbit if we stopped extracting at EOF.
*
testsuite/27_io/basic_istream/extractors_character/char/pr106248.cc:
New test.
*
testsuite/27_io/basic_istream/extractors_character/wchar_t/pr106248.cc:
New test.

(cherry picked from commit 5ae74944af1de032d4a27fad4a2287bd3a2163fd)

[Bug libstdc++/106248] [11/12 Regression] operator>>std::basic_istream at boundary condition behave differently in different opt levels

2022-07-25 Thread rguenth at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106248

Richard Biener  changed:

   What|Removed |Added

   Priority|P3  |P2

[Bug libstdc++/106248] [11/12 Regression] operator>>std::basic_istream at boundary condition behave differently in different opt levels

2022-07-12 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106248

Jonathan Wakely  changed:

   What|Removed |Added

  Known to fail||12.1.0
Summary|[11/12/13 Regression]   |[11/12 Regression]
   |operator>>std::basic_istrea |operator>>std::basic_istrea
   |m at boundary condition |m at boundary condition
   |behave differently in   |behave differently in
   |different opt levels|different opt levels

--- Comment #9 from Jonathan Wakely  ---
Fixed on trunk only so far.