From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 94C363858028; Mon, 14 Aug 2023 17:48:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 94C363858028 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1692035314; bh=GC4tZlSZgU4d3GoEsY7atsgZ8BlqxxpAqNTn8ISNG9g=; h=From:To:Subject:Date:In-Reply-To:References:From; b=K0H4IJ/D3SmbKTOXlIZA8Wnm0P1bPfWhOLkPc27IJ/YT80p4fyp75nEw93MpWtDsD jO4+zA8ikw5bxE6LhJ7DwhHOAXlTjAfgh2RuE4Ow9ZaRAtOBbF6OAyc4xlRam8mYwS ZCFh5hEYEH8lgq7Zt8edKGhnbbpL/zVjSHGI+CJs= From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/110990] `format_to_n` returns wrong value Date: Mon, 14 Aug 2023 17:48:33 +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: 13.2.1 X-Bugzilla-Keywords: 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: 13.3 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 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D110990 --- Comment #5 from CVS Commits --- The releases/gcc-13 branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:8f82863df33c63693a355d9244c315ef5cb2158e commit r13-7721-g8f82863df33c63693a355d9244c315ef5cb2158e Author: Jonathan Wakely Date: Fri Aug 11 23:02:44 2023 +0100 libstdc++: Fix std::format_to_n return value [PR110990] When writing to a contiguous iterator, std::format_to_n(out, n, ...) always returns out + n, even if it wrote fewer than n characters to the iterator. The problem is in the _M_finish() member function of the _Iter_sink specialization for contiguous iterators. _M_finish() calls _M_overflow() to update its count of characters written, so it can return the count of characters that would be written if there was room. But _M_overflow() assumes it's only called when the buffer is full, and so switches to the internal buffer. _M_finish() then thinks that if the internal buffer is in use, we already wrote at least n characters and so returns out+n as the output position. We can fix the problem by adding a check in _M_overflow() so that we don't update the count and switch to the internal buffer unless we've run out of room, i.e. _M_unused().size() is zero. The caller then needs to be prepared for _M_count not being the final total, and so add _M_used.size() to it. However, there's not actually any need for _M_finish() to call _M_overflow() to get the count. We now need to use _M_count and _M_used.size() to get the total anyway so _M_overflow() doesn't help with that. And we don't need to use _M_overflow() to flush unwritten characters to the output, because the specialization for contiguous iterators always writes directly to the output without buffering (except when we've exceeded the maximum number of characters, in which case we want to discard the buffered characters anyway). So _M_finish() can be simplified and can avoid calling _M_overflow(). This change also fixes some member functions of other sink classes to only call _M_overflow() when there are characters in the buffer, which is needed to meet _M_overflow's precondition that _M_used().size()!=3D0. libstdc++-v3/ChangeLog: PR libstdc++/110990 * include/std/format (_Seq_sink::get): Only call _M_overflow if its precondition is met. (_Iter_sink::_M_finish): Likewise. (_Iter_sink::_M_overflow): Only switch to the internal buffer after running out of space. (_Iter_sink::_M_finish): Do not use _M_overflow. (_Counting_sink::count): Likewise. * testsuite/std/format/functions/format_to_n.cc: Check cases where the output fits into the buffer. (cherry picked from commit 003016a40844701c48851020df672b70f3446bdb)=