https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118099

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <[email protected]>:

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

commit r17-5972-gf46b50adcf752de0e1e0e24e17f42a5075770f48
Author: Jonathan Wakely <[email protected]>
Date:   Thu Oct 22 23:39:56 2026 +0100

    libstdc++: Replace bump+rewind in basic_filebuf::overflow [PR118099]

    The fix for PR 118099 handled failure to write the pending output
    sequence to the external file (i.e. when _M_convert_to_external returns
    false or throws an exception) by rewinding the last character written to
    the output sequence.

    This commit changes basic_filebuf::overflow to not advance the put
    area's next pointer at all, so no rewinding is needed. Instead we can
    just increment the size passed to _M_convert_to_external to account for
    the extra character in the put area. This relies on the previous commit
    which changed _M_convert_to_external to no longer use pptr() when
    retrying after a partial codecvt conversion.  If _M_convert_to_external
    was still looking at pptr() directly and expecting it to have been
    bumped then we could not change overflow to no longer bump it.

    Because this change depends on that fix in _M_convert_to_external there
    is a potential ABI issue that needs care. If the new bump-less version
    of basic_filebuf::overflow gets inlined into a translation unit but the
    linker resolves its call to _M_convert_to_external to an old definition
    that still calls pptr(), we would not transfer the overflow character to
    the external file when retrying after a partial conversion. Although
    this scenario seems unlikely because std::filebuf and std::wfilebuf are
    both explicitly instantiated in libstdc++.so (and the explicit
    instantiations use the new definition of _M_convert_to_external) it
    would be safer to ensure the problem cannot occur.

    This commit adds an _M_convert_to_external(const _CharT*, streamsize)
    overload which takes a const pointer and moves all the logic from the
    old (non-const) overload to that new one.
    This ensures that the new bump-less overflow uses a new symbol
    with the new behaviour, and will never bind to an old definition that
    inspects pptr(). The old overload taking a non-const pointer needs to be
    preserved for ABI compatibility, but can be defined to simply forward
    its arguments to the new overload.

    With this change, instantiations of the old version of overflow can
    safely bind to either the old definition of _M_convert_to_external
    (which calls pptr()) or the new definition (which forwards to the new
    overload and so doesn't use pptr()) because both definitions are
    compatible with the old overflow. Instantiations of the new version of
    overflow will only ever bind to the new overload because it has a
    different mangled name.

    libstdc++-v3/ChangeLog:

            PR libstdc++/118099
            * config/abi/pre/gnu.ver: Tighten old patterns for basic_filebuf
            and export new symbols.
            * include/bits/fstream.tcc (basic_filebuf::overflow): Do not
            bump the next pointer for the overflow character. Pass const
            pointers to _M_convert_to_external.
            (_M_convert_to_external(_CharT*, streamsize)): Replace with ...
            (_M_convert_to_external(const _CharT*, streamsize)): Define new
            overload.
            * include/std/fstream (_M_convert_to_external): Declare new
            overload. Define old overload always_inline and suppress it
            for _GLIBCXX_INLINE_VERSION.

    Reviewed-by: Tomasz KamiÅski <[email protected]>

Reply via email to