Fix inconsistencies in random number generation.

The srand()/rand() interface was being intermixed with the
srandom()/random() one.  The later is now used throughout.

Changed the srand() and rand() BIFs to work deterministically if Bro
was given a seed file (addresses #825).  They also now wrap the
system's srandom() and random() instead of srand() and rand() as per
the above.
This commit is contained in:
Jon Siwek 2012-06-29 16:24:31 -05:00
parent 0e48fda6ff
commit 34ead91f99
7 changed files with 45 additions and 22 deletions

View file

@ -972,12 +972,12 @@ function sha256_hash_finish%(index: any%): string
## ##
## .. note:: ## .. note::
## ##
## This function is a wrapper about the function ``rand`` provided by ## This function is a wrapper about the function ``random``
## the OS. ## provided by the OS.
function rand%(max: count%): count function rand%(max: count%): count
%{ %{
int result; int result;
result = bro_uint_t(double(max) * double(rand()) / (RAND_MAX + 1.0)); result = bro_uint_t(double(max) * double(bro_random()) / (RAND_MAX + 1.0));
return new Val(result, TYPE_COUNT); return new Val(result, TYPE_COUNT);
%} %}
@ -989,11 +989,11 @@ function rand%(max: count%): count
## ##
## .. note:: ## .. note::
## ##
## This function is a wrapper about the function ``srand`` provided ## This function is a wrapper about the function ``srandom``
## by the OS. ## provided by the OS.
function srand%(seed: count%): any function srand%(seed: count%): any
%{ %{
srand(seed); bro_srandom(seed);
return 0; return 0;
%} %}

View file

@ -59,7 +59,7 @@ string Benchmark::RandomString(const int len)
"abcdefghijklmnopqrstuvwxyz"; "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
s[i] = values[rand() / (RAND_MAX / sizeof(values))]; s[i] = values[random() / (RAND_MAX / sizeof(values))];
return s; return s;
} }
@ -134,7 +134,7 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype)
break; break;
case TYPE_INT: case TYPE_INT:
val->val.int_val = rand(); val->val.int_val = random();
break; break;
case TYPE_TIME: case TYPE_TIME:
@ -148,11 +148,11 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype)
case TYPE_COUNT: case TYPE_COUNT:
case TYPE_COUNTER: case TYPE_COUNTER:
val->val.uint_val = rand(); val->val.uint_val = random();
break; break;
case TYPE_PORT: case TYPE_PORT:
val->val.port_val.port = rand() / (RAND_MAX / 60000); val->val.port_val.port = random() / (RAND_MAX / 60000);
val->val.port_val.proto = TRANSPORT_UNKNOWN; val->val.port_val.proto = TRANSPORT_UNKNOWN;
break; break;
@ -175,7 +175,7 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype)
// Then - common stuff // Then - common stuff
{ {
// how many entries do we have... // how many entries do we have...
unsigned int length = rand() / (RAND_MAX / 15); unsigned int length = random() / (RAND_MAX / 15);
Value** lvals = new Value* [length]; Value** lvals = new Value* [length];

View file

@ -633,12 +633,20 @@ static bool write_random_seeds(const char* write_file, uint32 seed,
static bool bro_rand_determistic = false; static bool bro_rand_determistic = false;
static unsigned int bro_rand_state = 0; static unsigned int bro_rand_state = 0;
static void bro_srand(unsigned int seed, bool deterministic) static void bro_srandom(unsigned int seed, bool deterministic)
{ {
bro_rand_state = seed; bro_rand_state = seed;
bro_rand_determistic = deterministic; bro_rand_determistic = deterministic;
srand(seed); srandom(seed);
}
void bro_srandom(unsigned int seed)
{
if ( bro_rand_determistic )
bro_rand_state = seed;
else
srandom(seed);
} }
void init_random_seed(uint32 seed, const char* read_file, const char* write_file) void init_random_seed(uint32 seed, const char* read_file, const char* write_file)
@ -705,7 +713,7 @@ void init_random_seed(uint32 seed, const char* read_file, const char* write_file
seeds_done = true; seeds_done = true;
} }
bro_srand(seed, seeds_done); bro_srandom(seed, seeds_done);
if ( ! hmac_key_set ) if ( ! hmac_key_set )
{ {

View file

@ -159,6 +159,10 @@ extern bool have_random_seed();
// predictable PRNG. // predictable PRNG.
long int bro_random(); long int bro_random();
// Calls the system srandom() function with the given seed if not running
// in deterministic mode, else it updates the state of the deterministic PRNG
void bro_srandom(unsigned int seed);
extern uint64 rand64bit(); extern uint64 rand64bit();
// Each event source that may generate events gets an internally unique ID. // Each event source that may generate events gets an internally unique ID.

View file

@ -1,6 +1,6 @@
185 985
236 474
805 738
47 4
996 634
498 473

View file

@ -0,0 +1,6 @@
985
474
738
974
371
638

View file

@ -1,6 +1,10 @@
# #
# @TEST-EXEC: bro %INPUT >out # @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: bro -b %INPUT do_seed=F >out.2
# @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff out
# @TEST-EXEC: btest-diff out.2
const do_seed = T &redef;
event bro_init() event bro_init()
{ {
@ -12,6 +16,7 @@ event bro_init()
print b; print b;
print c; print c;
if ( do_seed )
srand(575); srand(575);
local d = rand(1000); local d = rand(1000);