GH-1076: Fix bro_prng() implementation

The intermediate result of the PRNG used unsigned storage, preventing
the ( result < 0 ) branch from ever being evaluated.  This could cause
return values to exceed the modulus as well as RAND_MAX.

One interesting effect of this is potential for the rand() BIF to
return values outside the requested maximum limit.

Another interesting effect of this is that a PacketFilter may start
randomly dropping packets even if it was not configured for
random-packet-drops.
This commit is contained in:
Jon Siwek 2020-07-21 23:19:24 -07:00
parent dba764386b
commit 0f4eb9af02
3 changed files with 30 additions and 13 deletions

View file

@ -1186,18 +1186,22 @@ bool have_random_seed()
unsigned int bro_prng(unsigned int state)
{
// Use our own simple linear congruence PRNG to make sure we are
// predictable across platforms.
static const long int m = 2147483647;
static const long int a = 16807;
const long int q = m / a;
const long int r = m % a;
// predictable across platforms. (Lehmer RNG, Schrage's method)
constexpr uint32_t m = 2147483647;
constexpr uint32_t a = 16807;
constexpr uint32_t q = m / a;
constexpr uint32_t r = m % a;
state = a * ( state % q ) - r * ( state / q );
uint32_t rem = state % q;
uint32_t div = state / q;
int32_t s = a * rem;
int32_t t = r * div;
int32_t res = s - t;
if ( state <= 0 )
state += m;
if ( res < 0 )
res += m;
return state;
return res;
}
long int bro_random()