From 961df829b9a266adda89d3aa403d2625c5161e76 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Wed, 10 Jan 2024 16:52:52 +0500 Subject: [PATCH] Fix buffer overflow if output iterator is std::back_insert_iterator and value is escaped (debug format) Signed-off-by: Vladislav Shchapov --- include/fmt/format.h | 5 ++++- test/compile-test.cc | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index ebf85210a6d6..3d9e4d535950 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2388,9 +2388,12 @@ FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, size = code_point_index(s, to_unsigned(specs.precision)); bool is_debug = specs.type == presentation_type::debug; size_t width = 0; + + if (is_debug) size = write_escaped_string(counting_iterator{}, s).count(); + if (specs.width != 0) { if (is_debug) - width = write_escaped_string(counting_iterator{}, s).count(); + width = size; else width = compute_width(basic_string_view(data, size)); } diff --git a/test/compile-test.cc b/test/compile-test.cc index 171516c5cc2b..4d83033402d2 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -85,6 +85,16 @@ TEST(compile_test, format_default) { # endif } +TEST(compile_test, format_escape) { + EXPECT_EQ("\"string\"", fmt::format(FMT_COMPILE("{:?}"), "string")); + EXPECT_EQ("prefix \"string\"", + fmt::format(FMT_COMPILE("prefix {:?}"), "string")); + EXPECT_EQ("\"string\" suffix", + fmt::format(FMT_COMPILE("{:?} suffix"), "string")); + EXPECT_EQ("\"abc\"", fmt::format(FMT_COMPILE("{0:<5?}"), "abc")); + EXPECT_EQ("\"abc\" ", fmt::format(FMT_COMPILE("{0:<7?}"), "abc")); +} + TEST(compile_test, format_wide_string) { EXPECT_EQ(L"42", fmt::format(FMT_COMPILE(L"{}"), 42)); } @@ -288,7 +298,7 @@ TEST(compile_test, compile_format_string_literal) { // line 8635) #if (FMT_CPLUSPLUS >= 202002L || \ (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002)) && \ - ((!FMT_GLIBCXX_RELEASE || FMT_GLIBCXX_RELEASE >= 10) && \ + ((!FMT_GLIBCXX_RELEASE || FMT_GLIBCXX_RELEASE >= 10) && \ (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 10000) && \ (!FMT_MSC_VERSION || \ (FMT_MSC_VERSION >= 1928 && FMT_MSC_VERSION < 1930))) && \