From: Petr Špaček Date: Mon, 10 Dec 2018 17:43:00 +0000 (+0100) Subject: kr_random_coin: do not crash on invalid values X-Git-Tag: v3.2.0~13^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2fb36d26a25df9518b4e4de5c2cfcf363ce6b9a6;p=thirdparty%2Fknot-resolver.git kr_random_coin: do not crash on invalid values --- diff --git a/lib/utils.h b/lib/utils.h index fb59236b6..0ec283b0c 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -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);