mirror of https://gitee.com/bigwinds/arangodb
Bug fix/fix signed int overflow (#9717)
This commit is contained in:
parent
d68b4b4da0
commit
885504cd77
|
@ -100,7 +100,10 @@ int32_t RandomDevice::random(int32_t left, int32_t right) {
|
|||
return static_cast<int32_t>(random());
|
||||
}
|
||||
|
||||
uint32_t range = static_cast<uint32_t>(right - left + 1);
|
||||
TRI_ASSERT(right > left);
|
||||
int64_t r = static_cast<int64_t>(right) - static_cast<int64_t>(left) + 1;
|
||||
TRI_ASSERT(r >= 0 && r <= UINT32_MAX);
|
||||
uint32_t range = static_cast<uint32_t>(r);
|
||||
|
||||
switch (range) {
|
||||
case 0x00000002:
|
||||
|
@ -175,6 +178,7 @@ int32_t RandomDevice::power2(int32_t left, uint32_t mask) {
|
|||
}
|
||||
|
||||
int32_t RandomDevice::other(int32_t left, uint32_t range) {
|
||||
TRI_ASSERT(range != 0);
|
||||
uint32_t g = UINT32_MAX - UINT32_MAX % range;
|
||||
uint32_t r = random();
|
||||
int count = 0;
|
||||
|
@ -197,7 +201,10 @@ int32_t RandomDevice::other(int32_t left, uint32_t range) {
|
|||
|
||||
r %= range;
|
||||
|
||||
return left + static_cast<int32_t>(r);
|
||||
int32_t result = left + static_cast<int32_t>(r);
|
||||
TRI_ASSERT(result >= left);
|
||||
TRI_ASSERT(result < left + static_cast<int64_t>(range));
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -462,6 +469,7 @@ RandomGenerator::RandomType RandomGenerator::_type;
|
|||
thread_local std::unique_ptr<RandomDevice> RandomGenerator::_device(nullptr);
|
||||
|
||||
void RandomGenerator::initialize(RandomType type) {
|
||||
_device.reset();
|
||||
_type = type;
|
||||
}
|
||||
|
||||
|
@ -510,21 +518,16 @@ void RandomGenerator::ensureDeviceIsInitialized() {
|
|||
void RandomGenerator::shutdown() {
|
||||
// nothing to do...
|
||||
// thread-local devices will be released when their respective threads terminate.
|
||||
// however, we want to reset the device for testing
|
||||
_device.reset();
|
||||
}
|
||||
|
||||
|
||||
int16_t RandomGenerator::interval(int16_t left, int16_t right) {
|
||||
uint16_t value = static_cast<int16_t>(
|
||||
interval(static_cast<int32_t>(left), static_cast<int32_t>(right)));
|
||||
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
return static_cast<int16_t>(interval(static_cast<int32_t>(left), static_cast<int32_t>(right)));
|
||||
}
|
||||
|
||||
int32_t RandomGenerator::interval(int32_t left, int32_t right) {
|
||||
ensureDeviceIsInitialized();
|
||||
int32_t value = _device->interval(left, right);
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
return static_cast<int32_t>(interval(static_cast<int64_t>(left), static_cast<int64_t>(right)));
|
||||
}
|
||||
|
||||
int64_t RandomGenerator::interval(int64_t left, int64_t right) {
|
||||
|
@ -532,52 +535,19 @@ int64_t RandomGenerator::interval(int64_t left, int64_t right) {
|
|||
return left;
|
||||
}
|
||||
|
||||
int64_t value;
|
||||
|
||||
if (left == INT64_MIN && right == INT64_MAX) {
|
||||
uint64_t r1 = interval(UINT32_MAX);
|
||||
uint64_t r2 = interval(UINT32_MAX);
|
||||
|
||||
value = static_cast<int64_t>((r1 << 32) | r2);
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
}
|
||||
|
||||
if (left < 0) {
|
||||
if (right < 0) {
|
||||
uint64_t high = static_cast<uint64_t>(-left);
|
||||
uint64_t low = static_cast<uint64_t>(-right);
|
||||
uint64_t d = high - low;
|
||||
value = left + static_cast<int64_t>(interval(d));
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t low = static_cast<uint64_t>(-left);
|
||||
uint64_t d = low + static_cast<uint64_t>(right);
|
||||
uint64_t dRandom = interval(d);
|
||||
|
||||
if (dRandom < low) {
|
||||
value = -1 - static_cast<int64_t>(dRandom);
|
||||
} else {
|
||||
value = static_cast<int64_t>(dRandom - low);
|
||||
}
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
int64_t diff;
|
||||
if (left == INT64_MIN) {
|
||||
diff = right + static_cast<uint64_t>(INT64_MAX);
|
||||
} else {
|
||||
uint64_t high = static_cast<uint64_t>(right);
|
||||
uint64_t low = static_cast<uint64_t>(left);
|
||||
uint64_t d = high - low;
|
||||
value = left + static_cast<int64_t>(interval(d));
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
diff = static_cast<uint64_t>(right) - static_cast<uint64_t>(left);
|
||||
}
|
||||
int64_t value = left + interval(static_cast<uint64_t>(diff));
|
||||
TRI_ASSERT(value >= left && value <= right);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t RandomGenerator::interval(uint16_t right) {
|
||||
uint16_t value = static_cast<uint16_t>(interval(static_cast<uint32_t>(right)));
|
||||
TRI_ASSERT(value <= right);
|
||||
return value;
|
||||
return static_cast<uint16_t>(interval(static_cast<uint32_t>(right)));
|
||||
}
|
||||
|
||||
uint32_t RandomGenerator::interval(uint32_t right) {
|
||||
|
|
|
@ -78,6 +78,7 @@ class RandomGenerator {
|
|||
public:
|
||||
static void initialize(RandomType);
|
||||
static void shutdown();
|
||||
static void ensureDeviceIsInitialized();
|
||||
|
||||
static void seed(uint64_t);
|
||||
|
||||
|
@ -90,8 +91,6 @@ class RandomGenerator {
|
|||
static uint64_t interval(uint64_t);
|
||||
|
||||
private:
|
||||
static void ensureDeviceIsInitialized();
|
||||
|
||||
static RandomType _type;
|
||||
static thread_local std::unique_ptr<RandomDevice> _device;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite for RandomGenerator class
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2007-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Basics/Common.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Random/RandomGenerator.h"
|
||||
|
||||
using namespace arangodb;
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_ranges_int64) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
int64_t value;
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(0));
|
||||
EXPECT_EQ(-5115110072778412328, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(-20));
|
||||
EXPECT_EQ(-4189371921854575647, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(19));
|
||||
EXPECT_EQ(-6664312351376758686, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(0), int64_t(INT64_MAX));
|
||||
EXPECT_EQ(7199328709248114754, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(INT64_MAX));
|
||||
EXPECT_EQ(7812659160807914514, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(0), int64_t(0));
|
||||
EXPECT_EQ(0, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(INT64_MIN));
|
||||
EXPECT_EQ(INT64_MIN, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MAX), int64_t(INT64_MAX));
|
||||
EXPECT_EQ(INT64_MAX, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(5), int64_t(15));
|
||||
EXPECT_EQ(12, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(5), int64_t(15));
|
||||
EXPECT_EQ(6, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(5), int64_t(15));
|
||||
EXPECT_EQ(13, value);
|
||||
|
||||
value = RandomGenerator::interval(int64_t(INT64_MIN), int64_t(-49874753588));
|
||||
EXPECT_EQ(-6563046468452533532, value);
|
||||
}
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_ranges_int32) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
int32_t value;
|
||||
value = RandomGenerator::interval(int32_t(INT32_MIN), int32_t(0));
|
||||
EXPECT_EQ(-1190954371, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(0), int32_t(INT32_MAX));
|
||||
EXPECT_EQ(1694838488, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(INT32_MIN), int32_t(INT32_MAX));
|
||||
EXPECT_EQ(-975414162, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(0), int32_t(0));
|
||||
EXPECT_EQ(0, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(INT32_MIN), int32_t(INT32_MIN));
|
||||
EXPECT_EQ(INT32_MIN, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(INT32_MAX), int32_t(INT32_MAX));
|
||||
EXPECT_EQ(INT32_MAX, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(5), int32_t(15));
|
||||
EXPECT_EQ(9, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(5), int32_t(15));
|
||||
EXPECT_EQ(6, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(5), int32_t(15));
|
||||
EXPECT_EQ(11, value);
|
||||
|
||||
value = RandomGenerator::interval(int32_t(INT32_MIN), int32_t(-485774));
|
||||
EXPECT_EQ(-1208965022, value);
|
||||
}
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_ranges_int16) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
int16_t value;
|
||||
value = RandomGenerator::interval(int16_t(INT16_MIN), int16_t(0));
|
||||
EXPECT_EQ(-30601, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(0), int16_t(INT16_MAX));
|
||||
EXPECT_EQ(11992, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(INT16_MIN), int16_t(INT16_MAX));
|
||||
EXPECT_EQ(-9106, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(0), int16_t(0));
|
||||
EXPECT_EQ(0, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(INT16_MIN), int16_t(INT16_MIN));
|
||||
EXPECT_EQ(INT16_MIN, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(INT16_MAX), int16_t(INT16_MAX));
|
||||
EXPECT_EQ(INT16_MAX, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(5), int16_t(15));
|
||||
EXPECT_EQ(9, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(5), int16_t(15));
|
||||
EXPECT_EQ(6, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(5), int16_t(15));
|
||||
EXPECT_EQ(11, value);
|
||||
|
||||
value = RandomGenerator::interval(int16_t(INT16_MIN), int16_t(-4854));
|
||||
EXPECT_EQ(-16442, value);
|
||||
}
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_interval_uint64) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
uint64_t value;
|
||||
value = RandomGenerator::interval(uint64_t(0));
|
||||
EXPECT_EQ(0U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint64_t(UINT64_MAX));
|
||||
EXPECT_EQ(13331634000931139288U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint64_t(5));
|
||||
EXPECT_EQ(4U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint64_t(5));
|
||||
EXPECT_EQ(1U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint64_t(5));
|
||||
EXPECT_EQ(0U, value);
|
||||
}
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_interval_uint32) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
uint32_t value;
|
||||
value = RandomGenerator::interval(uint32_t(0));
|
||||
EXPECT_EQ(0U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint32_t(UINT32_MAX));
|
||||
EXPECT_EQ(3104012925U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint32_t(5));
|
||||
EXPECT_EQ(4U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint32_t(5));
|
||||
EXPECT_EQ(4U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint32_t(5));
|
||||
EXPECT_EQ(1U, value);
|
||||
}
|
||||
|
||||
TEST(RandomGeneratorTest, test_RandomGeneratorMersenne_interval_uint16) {
|
||||
RandomGenerator::initialize(RandomGenerator::RandomType::MERSENNE);
|
||||
RandomGenerator::ensureDeviceIsInitialized();
|
||||
RandomGenerator::seed(0xdeadbeef);
|
||||
|
||||
uint16_t value;
|
||||
value = RandomGenerator::interval(uint16_t(0));
|
||||
EXPECT_EQ(0U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint16_t(UINT16_MAX));
|
||||
EXPECT_EQ(31357U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint16_t(5));
|
||||
EXPECT_EQ(4U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint16_t(5));
|
||||
EXPECT_EQ(4U, value);
|
||||
|
||||
value = RandomGenerator::interval(uint16_t(5));
|
||||
EXPECT_EQ(1U, value);
|
||||
}
|
|
@ -78,6 +78,7 @@ set(ARANGODB_TESTS_SOURCES
|
|||
Basics/HashSetTest.cpp
|
||||
Basics/InifileParserTest.cpp
|
||||
Basics/LoggerTest.cpp
|
||||
Basics/RandomTest.cpp
|
||||
Basics/StringBufferTest.cpp
|
||||
Basics/StringUtilsTest.cpp
|
||||
Basics/VelocyPackHelper-test.cpp
|
||||
|
|
Loading…
Reference in New Issue