Fix integer overflow in ToNtpUnits helper

Bug: b/232293787
Change-Id: I7f781ff38a23ae829447e5274ec7f6493de8195d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/262240
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Emil Lundmark <lndmrk@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36863}
This commit is contained in:
Danil Chapovalov
2022-05-12 11:09:29 +02:00
committed by WebRTC LUCI CQ
parent 1f1abd1dcc
commit f987c78d14
2 changed files with 19 additions and 1 deletions

View File

@ -14,6 +14,7 @@
#include <stdint.h>
#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<int32_t>(delta.us()) * (int64_t{1} << 32)) /
1'000'000;
}
// Converts interval from compact ntp (1/2^16 seconds) resolution to TimeDelta.

View File

@ -9,6 +9,10 @@
*/
#include "modules/rtp_rtcp/source/time_util.h"
#include <cstdint>
#include <limits>
#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<int64_t>::max() - 1));
ToNtpUnits(TimeDelta::Micros(std::numeric_limits<int64_t>::min() + 1));
}
} // namespace webrtc