https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105580
--- Comment #20 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Tomasz Kaminski <[email protected]>: https://gcc.gnu.org/g:a068d1b7c9da60a9b21efa4baf65f7325211be12 commit r17-376-ga068d1b7c9da60a9b21efa4baf65f7325211be12 Author: Tomasz KamiÅski <[email protected]> Date: Wed Jan 7 14:01:41 2026 +0100 libstdc++: Rework istreambuf_iterator::_M_sbuf handling to slice null-dereference warning [PR105580] The warning was produced by following sequence, given an istream_iterator<char> it, such that *it will result in hitting EoF in it->_M_get(), and thus clearing _M_sbuf, the subsequent call to ++it, will result in _M_sbuf->sbumpc() call on null pointer. This is however an false-positive, as in such situation it == istream_iteator() returns true, and the iterator should not be incremented in first place. This patch addresses the above by clearing the _M_sbuf in operator++, instead of _M_get(). This removes the need for making _M_sbuf mutable, and thus make the implementation conforming with regards to C++11 [res.on.data.races] p3. Also removes no longer needed "-Wnull-dereference" disabling pragmas from streambuf (see r16-7844-gbfc2b87f8244a1). This change should have zero or positive performance impact on the usual iteration patterns, in form: while (it != end) { process(*it); ++it; } In case when it is end-of-stream iterator, the it != end returns in one call of _M_sbuf->sgetc() both before and after the change. However we do not modify _M_sbuf in this case. For non-empty range, we replace call to _M_sbuf->sbumpc() with _M_sbuf->snextc() in pre-increment, and extract the check against EoF from *it to ++it. However, as _M_sbuf is now cleared during increment, so last it != end check avoids _M_sbuf->sgetc() call to check against EoF. However, this change impact the behavior of the post-increment (*it++), as we now load both current character (for return value) and next character (to check against EoF). In consequence we call both sgetc() and snextc(), in contrast to previous single sbumpc() call. PR libstdc++/105580 libstdc++-v3/ChangeLog: * include/bits/streambuf_iterator.h (istreambuf_iterator::_M_sbuf): Remove mutable and adjust whitespace. (istreambuf_iterator::_M_c): Adjust whitespace. (istreambuf_iterator::operator++()): Clear _M_sbuf if next character is EoF. (istreambuf_iterator::operator++(int)): Use _M_sbuf->sgetc() to load current character, and define in terms of ++*this. (istreambuf_iterator::_M_get()): Do not clear _M_sbuf in case of EoF. * include/std/streambuf (streambuf::gptr, streambuf::egptr) (streambuf::gbump): Remove surrounding pragma disabling -Wnull-dereference. * testsuite/24_iterators/istreambuf_iterator/2.cc: Test for using multiple iterators to same rdbuf. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz KamiÅski <[email protected]>
