LibC: Cleanup and fix random functions
I was getting the size of random state incorrectly and ended up with double the size user gave us leading to OOB access :D Also remove hardcoded type -> size mappings and just use a looup table
This commit is contained in:
@@ -625,11 +625,6 @@ static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
|||||||
static constexpr uint64_t s_rand_increment = 1442695040888963407;
|
static constexpr uint64_t s_rand_increment = 1442695040888963407;
|
||||||
static uint64_t s_rand_state;
|
static uint64_t s_rand_state;
|
||||||
|
|
||||||
static constexpr uint32_t rotr32(uint32_t x, unsigned r)
|
|
||||||
{
|
|
||||||
return x >> r | x << (-r & 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<BAN::integral T>
|
template<BAN::integral T>
|
||||||
static inline int rand_impl(T& state)
|
static inline int rand_impl(T& state)
|
||||||
{
|
{
|
||||||
@@ -644,6 +639,10 @@ static inline int rand_impl(T& state)
|
|||||||
state = x * s_rand_multiplier + s_rand_increment;
|
state = x * s_rand_multiplier + s_rand_increment;
|
||||||
x ^= x >> 18;
|
x ^= x >> 18;
|
||||||
|
|
||||||
|
constexpr auto rotr32 = [](uint32_t x, unsigned r) {
|
||||||
|
return x >> r | x << (-r & 31);
|
||||||
|
};
|
||||||
|
|
||||||
return rotr32(x >> 27, count) % RAND_MAX;
|
return rotr32(x >> 27, count) % RAND_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,25 +670,21 @@ struct random_state_t
|
|||||||
uint32_t table[];
|
uint32_t table[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr size_t s_random_state_sizes[] { 8, 32, 64, 128, 256 };
|
||||||
|
static constexpr size_t s_random_state_size_count = sizeof(s_random_state_sizes) / sizeof(*s_random_state_sizes);
|
||||||
|
|
||||||
static char* s_random_state;
|
static char* s_random_state;
|
||||||
|
|
||||||
static size_t get_random_state_size()
|
static size_t get_random_state_size()
|
||||||
{
|
{
|
||||||
auto& state = *reinterpret_cast<random_state_t*>(s_random_state);
|
const auto& state = *reinterpret_cast<random_state_t*>(s_random_state);
|
||||||
switch (state.type)
|
ASSERT(state.type < s_random_state_size_count);
|
||||||
{
|
return s_random_state_sizes[state.type];
|
||||||
case 0: return 8;
|
|
||||||
case 1: return 32;
|
|
||||||
case 2: return 64;
|
|
||||||
case 3: return 128;
|
|
||||||
case 4: return 256;
|
|
||||||
}
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t get_random_table_size()
|
static size_t get_random_table_size()
|
||||||
{
|
{
|
||||||
return get_random_state_size() / sizeof(uint32_t) - 1;
|
return (get_random_state_size() - offsetof(random_state_t, table)) / sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
long random(void)
|
long random(void)
|
||||||
@@ -712,22 +707,13 @@ char* initstate(unsigned seed, char* statebuf, size_t size)
|
|||||||
if (size < 8)
|
if (size < 8)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
auto& new_state = *reinterpret_cast<random_state_t*>(statebuf);
|
|
||||||
|
|
||||||
if (size < 8)
|
|
||||||
new_state.type = 0;
|
|
||||||
else if (size < 32)
|
|
||||||
new_state.type = 1;
|
|
||||||
else if (size < 64)
|
|
||||||
new_state.type = 2;
|
|
||||||
else if (size < 128)
|
|
||||||
new_state.type = 3;
|
|
||||||
else if (size < 256)
|
|
||||||
new_state.type = 4;
|
|
||||||
|
|
||||||
char* old_state = s_random_state;
|
char* old_state = s_random_state;
|
||||||
s_random_state = statebuf;
|
s_random_state = statebuf;
|
||||||
|
|
||||||
|
auto& new_state = *reinterpret_cast<random_state_t*>(s_random_state);
|
||||||
|
for (size_t i = 0; i < s_random_state_size_count && size >= s_random_state_sizes[i]; i++)
|
||||||
|
new_state.type = i;
|
||||||
|
|
||||||
const size_t table_size = get_random_table_size();
|
const size_t table_size = get_random_table_size();
|
||||||
new_state.idx1 = 0;
|
new_state.idx1 = 0;
|
||||||
new_state.idx2 = table_size - 1;
|
new_state.idx2 = table_size - 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user