diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index f4ffeb67..ec636247 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -704,7 +704,12 @@ FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits( if (handler.fixed) { // Adjust fixed precision by exponent because it is relative to decimal // point. - handler.precision += exp + handler.exp10; + int precision_offset = exp + handler.exp10; + if (precision_offset > 0 && + handler.precision > max_value() - precision_offset) { + throw format_error("number is too big"); + } + handler.precision += precision_offset; // Check if precision is satisfied just by leading zeros, e.g. // format("{:.2f}", 0.001) gives "0.00" without generating any digits. if (handler.precision <= 0) { diff --git a/test/format-test.cc b/test/format-test.cc index 9233a87b..0b551f99 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -934,6 +934,9 @@ TEST(format_test, precision) { EXPECT_THROW_MSG((void)fmt::format(runtime("{:.{}e}"), 42.0, fmt::detail::max_value()), format_error, "number is too big"); + EXPECT_THROW_MSG( + (void)fmt::format("{:.2147483646f}", -2.2121295195081227E+304), + format_error, "number is too big"); EXPECT_EQ("st", fmt::format("{0:.2}", "str")); } diff --git a/test/fuzzing/float.cc b/test/fuzzing/float.cc index b3780e1d..d4c9e4f5 100644 --- a/test/fuzzing/float.cc +++ b/test/fuzzing/float.cc @@ -12,7 +12,7 @@ void check_round_trip(fmt::string_view format_str, double value) { auto buffer = fmt::memory_buffer(); - fmt::format_to(buffer, format_str, value); + fmt::format_to(std::back_inserter(buffer), format_str, value); if (std::isnan(value)) { auto nan = std::signbit(value) ? "-nan" : "nan";