diff --git a/include/fmt/format.h b/include/fmt/format.h index 62db5a0d458b..3c05ac1deec1 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -505,8 +505,8 @@ constexpr auto to_pointer(OutputIt, size_t) -> T* { template FMT_CONSTEXPR20 auto to_pointer(basic_appender it, size_t n) -> T* { buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); auto size = buf.size(); - buf.try_reserve(size + n); if (buf.capacity() < size + n) return nullptr; buf.try_resize(size + n); return buf.data() + size; diff --git a/test/format-test.cc b/test/format-test.cc index 1c907c87183e..548331e6beb5 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1821,7 +1821,9 @@ TEST(format_test, big_print) { } // Windows CRT implements _IOLBF incorrectly (full buffering). -#if FMT_USE_FCNTL && !defined(_WIN32) +#if FMT_USE_FCNTL + +#ifndef _WIN32 TEST(format_test, line_buffering) { auto pipe = fmt::pipe(); @@ -1847,6 +1849,25 @@ TEST(format_test, line_buffering) { } #endif +TEST(format_test, buffer_boundary) { + auto pipe = fmt::pipe(); + + auto write_end = pipe.write_end.fdopen("w"); + setvbuf(write_end.get(), nullptr, _IOFBF, 4096); + for(int i = 3 ; i < 4094 ; i++) + write_end.print("{}", (i % 73) != 0 ? 'x' : '\n'); + write_end.print("{} {}", 1234, 567); + write_end.close(); + + auto read_end = pipe.read_end.fdopen("r"); + char buf[4091] = {}; + fread(buf, 1, sizeof(buf), read_end.get()); + fgets(buf, sizeof(buf), read_end.get()); + EXPECT_STREQ(buf, "1234 567"); +} + +#endif // FMT_USE_FCNTL + struct deadlockable { int value = 0; mutable std::mutex mutex;