diff --git a/modules/rtp_rtcp/source/time_util.h b/modules/rtp_rtcp/source/time_util.h index 5e72bba3b9..9ff444b12e 100644 --- a/modules/rtp_rtcp/source/time_util.h +++ b/modules/rtp_rtcp/source/time_util.h @@ -14,6 +14,7 @@ #include #include "api/units/time_delta.h" +#include "rtc_base/numerics/safe_conversions.h" #include "system_wrappers/include/ntp_time.h" namespace webrtc { @@ -35,11 +36,14 @@ inline uint32_t CompactNtp(NtpTime ntp) { uint32_t SaturatedToCompactNtp(TimeDelta delta); // Convert interval to the NTP time resolution (1/2^32 seconds ~= 0.2 ns). +// For deltas with absolute value larger than 35 minutes result is unspecified. inline constexpr int64_t ToNtpUnits(TimeDelta delta) { // For better precision `delta` is taken with best TimeDelta precision (us), // then multiplaction and conversion to seconds are swapped to avoid float // arithmetic. - return (delta.us() * (int64_t{1} << 32)) / 1'000'000; + // 2^31 us ~= 35.8 minutes. + return (rtc::saturated_cast(delta.us()) * (int64_t{1} << 32)) / + 1'000'000; } // Converts interval from compact ntp (1/2^16 seconds) resolution to TimeDelta. diff --git a/modules/rtp_rtcp/source/time_util_unittest.cc b/modules/rtp_rtcp/source/time_util_unittest.cc index f77c3c6e5d..b3d557fd83 100644 --- a/modules/rtp_rtcp/source/time_util_unittest.cc +++ b/modules/rtp_rtcp/source/time_util_unittest.cc @@ -9,6 +9,10 @@ */ #include "modules/rtp_rtcp/source/time_util.h" +#include +#include + +#include "api/units/time_delta.h" #include "test/gtest.h" namespace webrtc { @@ -109,6 +113,16 @@ TEST(TimeUtilTest, ToNtpUnits) { // 1 us ~= 4'294.97 NTP units. ToNtpUnits makes no rounding promises. EXPECT_GE(ToNtpUnits(TimeDelta::Micros(1)), 4'294); EXPECT_LE(ToNtpUnits(TimeDelta::Micros(1)), 4'295); + + // Test near maximum and minimum supported values. + static constexpr int64_t k35MinutesInNtpUnits = int64_t{35 * 60} << 32; + EXPECT_EQ(ToNtpUnits(TimeDelta::Seconds(35 * 60)), k35MinutesInNtpUnits); + EXPECT_EQ(ToNtpUnits(TimeDelta::Seconds(-35 * 60)), -k35MinutesInNtpUnits); + + // The result for too large or too small values is unspecified, but + // shouldn't cause integer overflow or other undefined behavior. + ToNtpUnits(TimeDelta::Micros(std::numeric_limits::max() - 1)); + ToNtpUnits(TimeDelta::Micros(std::numeric_limits::min() + 1)); } } // namespace webrtc