From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 72D64385C40F; Tue, 12 Jul 2022 22:40:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 72D64385C40F From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/106248] [11/12/13 Regression] operator>>std::basic_istream at boundary condition behave differently in different opt levels Date: Tue, 12 Jul 2022 22:40:13 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: 11.2.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: redi at gcc dot gnu.org X-Bugzilla-Target-Milestone: 11.4 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Jul 2022 22:40:13 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D106248 --- Comment #8 from CVS Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:5ae74944af1de032d4a27fad4a2287bd3a2163fd commit r13-1651-g5ae74944af1de032d4a27fad4a2287bd3a2163fd 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() !=3D goodb= it 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.=