1
0
Fork 0

Bug fix/fix signed int overflow (#9717)

This commit is contained in:
Jan 2019-08-20 10:48:46 +02:00 committed by GitHub
parent d68b4b4da0
commit 885504cd77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 242 additions and 55 deletions

View File

@ -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) {

View File

@ -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;
};

217
tests/Basics/RandomTest.cpp Normal file
View File

@ -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);
}

View File

@ -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