Commit 2fb36d26 authored by Petr Špaček's avatar Petr Špaček Committed by Vladimír Čunát

kr_random_coin: do not crash on invalid values

parent a074e2f1
......@@ -189,7 +189,7 @@ KR_EXPORT
void kr_rnd_buffered(void *data, unsigned int size);
/** Return a few random bytes. */
static inline uint64_t kr_rand_bytes(int size)
static inline uint64_t kr_rand_bytes(unsigned int size)
{
uint64_t result;
if (size <= 0 || size > sizeof(result)) {
......@@ -204,25 +204,27 @@ static inline uint64_t kr_rand_bytes(int size)
* (Tested via reading assembly from usual gcc -O2 setup.)
* Alternatively we could waste more rnd bytes, but that seemed worse. */
result = 0;
for (int i = 0; i < size; ++ i) {
for (unsigned int i = 0; i < size; ++ i) {
result |= ((size_t)data[i]) << (i * 8);
}
return result;
}
/** Throw a pseudo-random coin, succeeding approximately with probability nomin/denomin.
* - low precision, only one byte of randomness
* - the most extreme bias is 1:255
* - low precision, only one byte of randomness (or none with extreme parameters)
* - tip: use !kr_rand_coin() to get the complementary probability
*/
static inline bool kr_rand_coin(int nomin, int denomin)
static inline bool kr_rand_coin(unsigned int nomin, unsigned int denomin)
{
if (nomin < 0 || denomin <= 0 || nomin > denomin) {
kr_log_error("kr_rand_coin(): EINVAL\n");
abort();
}
/* This function might be called with non-constant values
* so we try to handle odd corner cases instead of crash. */
if (nomin >= denomin)
return true;
else if (nomin <= 0)
return false;
/* threshold = how many parts from 256 are a success */
int threshold = (nomin * 256 + /*rounding*/ denomin / 2) / denomin;
unsigned int threshold = (nomin * 256 + /*rounding*/ denomin / 2) / denomin;
if (threshold == 0) threshold = 1;
if (threshold == 256) threshold = 255;
return (kr_rand_bytes(1) < threshold);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment