Fix some signed overflow errors causing undefined behavior (in theory).
BUG=webrtc:5491 Review URL: https://codereview.webrtc.org/1744183002 Cr-Commit-Position: refs/heads/master@{#11832}
This commit is contained in:
parent
5711c8d1f8
commit
d802b5b7c3
@ -412,7 +412,9 @@ int CountIPMaskBits(IPAddress mask) {
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
// Counts the trailing 0s in the word.
|
||||
unsigned int zeroes = 32;
|
||||
word_to_count &= -static_cast<int32_t>(word_to_count);
|
||||
// This could also be written word_to_count &= -word_to_count, but
|
||||
// MSVC emits warning C4146 when negating an unsigned number.
|
||||
word_to_count &= ~word_to_count + 1; // Isolate lowest set bit.
|
||||
if (word_to_count) zeroes--;
|
||||
if (word_to_count & 0x0000FFFF) zeroes -= 16;
|
||||
if (word_to_count & 0x00FF00FF) zeroes -= 8;
|
||||
@ -522,4 +524,4 @@ IPAddress GetAnyIP(int family) {
|
||||
return rtc::IPAddress();
|
||||
}
|
||||
|
||||
} // Namespace rtc
|
||||
} // namespace rtc
|
||||
|
||||
@ -12,9 +12,28 @@
|
||||
#define WEBRTC_BASE_MATHUTILS_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265359f
|
||||
#endif
|
||||
|
||||
// Given two numbers |x| and |y| such that x >= y, computes the difference
|
||||
// x - y without causing undefined behavior due to signed overflow.
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type unsigned_difference(T x, T y) {
|
||||
static_assert(
|
||||
std::is_signed<T>::value,
|
||||
"Function unsigned_difference is only meaningful for signed types.");
|
||||
RTC_DCHECK_GE(x, y);
|
||||
typedef typename std::make_unsigned<T>::type unsigned_type;
|
||||
// int -> unsigned conversion repeatedly adds UINT_MAX + 1 until the number
|
||||
// can be represented as an unsigned. Since we know that the actual
|
||||
// difference x - y can be represented as an unsigned, it is sufficient to
|
||||
// compute the difference modulo UINT_MAX + 1, i.e using unsigned arithmetic.
|
||||
return static_cast<unsigned_type>(x) - static_cast<unsigned_type>(y);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_BASE_MATHUTILS_H_
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/base/mathutils.h" // unsigned difference
|
||||
#include "webrtc/base/random.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -118,7 +119,7 @@ void BucketTestSignedInterval(unsigned int bucket_count,
|
||||
|
||||
ASSERT_GE(high, low);
|
||||
ASSERT_GE(bucket_count, 2u);
|
||||
uint32_t interval = static_cast<uint32_t>(high - low + 1);
|
||||
uint32_t interval = unsigned_difference<int32_t>(high, low) + 1;
|
||||
uint32_t numbers_per_bucket;
|
||||
if (interval == 0) {
|
||||
// The computation high - low + 1 should be 2^32 but overflowed
|
||||
@ -134,7 +135,7 @@ void BucketTestSignedInterval(unsigned int bucket_count,
|
||||
int32_t sample = prng->Rand(low, high);
|
||||
EXPECT_LE(low, sample);
|
||||
EXPECT_GE(high, sample);
|
||||
buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++;
|
||||
buckets[unsigned_difference<int32_t>(sample, low) / numbers_per_bucket]++;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bucket_count; i++) {
|
||||
@ -158,7 +159,7 @@ void BucketTestUnsignedInterval(unsigned int bucket_count,
|
||||
|
||||
ASSERT_GE(high, low);
|
||||
ASSERT_GE(bucket_count, 2u);
|
||||
uint32_t interval = static_cast<uint32_t>(high - low + 1);
|
||||
uint32_t interval = high - low + 1;
|
||||
uint32_t numbers_per_bucket;
|
||||
if (interval == 0) {
|
||||
// The computation high - low + 1 should be 2^32 but overflowed
|
||||
@ -174,7 +175,7 @@ void BucketTestUnsignedInterval(unsigned int bucket_count,
|
||||
uint32_t sample = prng->Rand(low, high);
|
||||
EXPECT_LE(low, sample);
|
||||
EXPECT_GE(high, sample);
|
||||
buckets[static_cast<uint32_t>(sample - low) / numbers_per_bucket]++;
|
||||
buckets[(sample - low) / numbers_per_bucket]++;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bucket_count; i++) {
|
||||
|
||||
@ -56,7 +56,7 @@ class RollingAccumulator {
|
||||
// Remove oldest sample.
|
||||
T sample_to_remove = samples_[next_index_];
|
||||
sum_ -= sample_to_remove;
|
||||
sum_2_ -= sample_to_remove * sample_to_remove;
|
||||
sum_2_ -= static_cast<double>(sample_to_remove) * sample_to_remove;
|
||||
if (sample_to_remove >= max_) {
|
||||
max_stale_ = true;
|
||||
}
|
||||
@ -70,7 +70,7 @@ class RollingAccumulator {
|
||||
// Add new sample.
|
||||
samples_[next_index_] = sample;
|
||||
sum_ += sample;
|
||||
sum_2_ += sample * sample;
|
||||
sum_2_ += static_cast<double>(sample) * sample;
|
||||
if (count_ == 1 || sample >= max_) {
|
||||
max_ = sample;
|
||||
max_stale_ = false;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user