diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 39369addd7ce..9a53c83bd284 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -431,12 +431,22 @@ struct chrono_formatter { explicit chrono_formatter(FormatContext& ctx, OutputIt o, std::chrono::duration d) : context(ctx), out(o), val(d.count()) { + constexpr bool is_floating_point = std::is_floating_point::value; + if (is_floating_point && !std::isfinite(d.count())) { + FMT_THROW(format_error("floating point duration is NaN or Inf")); + } if (d.count() < 0) { d = -d; *out++ = '-'; } + s = std::chrono::duration_cast(d); ms = std::chrono::duration_cast(d - s); + if (is_floating_point) { + if (!std::isfinite(s.count()) || !std::isfinite(ms.count())) { + FMT_THROW(format_error("internal overflow of floating point duration")); + } + } } int hour() const { return to_int(mod((s.count() / 3600), 24)); } diff --git a/test/chrono-test.cc b/test/chrono-test.cc index e3615e856022..8775e544c37e 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -316,16 +316,16 @@ TEST(ChronoTest, NegativeDuration) { TEST(ChronoTest, DurationIsFloatNaN) { const std::chrono::duration d{std::nanf("1")}; - auto ignored=fmt::format("{:%I}",d); + EXPECT_THROW(fmt::format("{:%I}",d),fmt::format_error); } TEST(ChronoTest, DurationIsDoubleNaN) { const std::chrono::duration d{std::nan("1")}; - auto ignored=fmt::format("{:%I}",d); + EXPECT_THROW(fmt::format("{:%I}",d),fmt::format_error); } TEST(ChronoTest, OverflowingFloat) { const std::chrono::duration d{std::numeric_limits::max()*0.5f}; - auto ignored=fmt::format("{:%I}",d); + EXPECT_THROW(fmt::format("{:%I}",d),fmt::format_error); } #endif // FMT_STATIC_THOUSANDS_SEPARATOR