llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: llvmbot <details> <summary>Changes</summary> Backport 372dc97670f7b3ce422dc26e5f626b2711426e8d Requested by: @<!-- -->frederick-vs-ja --- Full diff: https://github.com/llvm/llvm-project/pull/226868.diff 2 Files Affected: - (modified) libcxx/include/__format/buffer.h (+12) - (added) libcxx/test/std/utilities/format/format.functions/bug_154670.pass.cpp (+74) ``````````diff diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h index e7454f08f45d5..fbb67b02a6d17 100644 --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -250,6 +250,10 @@ class __output_buffer { __first += __chunk; __n -= __chunk; } while (__n); + + // push_back needs a free code unit, which the last chunk may have used. + if (__size_ == __capacity_) + __prepare_write(0); } /// A std::transform wrapper. @@ -276,6 +280,10 @@ class __output_buffer { __first += __chunk; __n -= __chunk; } while (__n); + + // push_back needs a free code unit, which the last chunk may have used. + if (__size_ == __capacity_) + __prepare_write(0); } /// A \c fill_n wrapper. @@ -293,6 +301,10 @@ class __output_buffer { __size_ += __chunk; __n -= __chunk; } while (__n); + + // push_back needs a free code unit, which the last chunk may have used. + if (__size_ == __capacity_) + __prepare_write(0); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __capacity() const { return __capacity_; } diff --git a/libcxx/test/std/utilities/format/format.functions/bug_154670.pass.cpp b/libcxx/test/std/utilities/format/format.functions/bug_154670.pass.cpp new file mode 100644 index 0000000000000..7f36d7d95b6f9 --- /dev/null +++ b/libcxx/test/std/utilities/format/format.functions/bug_154670.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++20 + +// XFAIL: availability-fp_to_chars-missing + +// https://llvm.org/PR154670 +// +// Formatting into a back_insert_iterator of a string, vector or deque goes +// through a fixed-size buffer. Tests that the code unit written after an +// argument or a fill that ends at a multiple of the buffer's size is not +// written past the end of that buffer. + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <deque> +#include <format> +#include <iterator> +#include <string> +#include <vector> + +#include "make_string.h" +#include "test_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template <class CharT, class Container> +void test(std::size_t size) { + const std::basic_string<CharT> arg(size, CharT('a')); + const std::basic_string<CharT> expected = arg + CharT('!'); + + { // The argument is copied. + Container out; + std::format_to(std::back_inserter(out), SV("{}!"), arg); + assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end())); + } + if (size != 0) { // The argument's padding is filled. + Container out; + std::format_to(std::back_inserter(out), SV("{:a<{}}!"), SV(""), size); + assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end())); + } + for (std::size_t n : {size, size + 1, size + 2}) { + Container out; + auto result = std::format_to_n(std::back_inserter(out), n, SV("{}!"), arg); + assert(result.size == static_cast<std::ptrdiff_t>(expected.size())); + std::size_t written = std::min(n, expected.size()); + assert(std::equal(out.begin(), out.end(), expected.begin(), expected.begin() + written)); + } +} + +template <class CharT> +void test() { + for (std::size_t size : {0, 1, 255, 256, 257, 511, 512, 513, 1024}) { + test<CharT, std::basic_string<CharT>>(size); + test<CharT, std::vector<CharT>>(size); + test<CharT, std::deque<CharT>>(size); + } +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} `````````` </details> https://github.com/llvm/llvm-project/pull/226868 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
