mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 23:28:20 +00:00
Add zeek::max_random() & fix misuse of RAND_MAX w/ zeek::random_number()
In deterministic mode, RAND_MAX is not related to the result of zeek::random_number() (formerly bro_random()), but some logic was using RAND_MAX as indication of the possible range of values. The new zeek::max_random() will give the correct upper-bound regardless of whether deterministic-mode is used.
This commit is contained in:
parent
bde38893ce
commit
d486af06b1
6 changed files with 24 additions and 9 deletions
|
@ -18,7 +18,7 @@ void PacketFilter::AddSrc(const IPAddr& src, uint32_t tcp_flags, double probabil
|
||||||
{
|
{
|
||||||
Filter* f = new Filter;
|
Filter* f = new Filter;
|
||||||
f->tcp_flags = tcp_flags;
|
f->tcp_flags = tcp_flags;
|
||||||
f->probability = uint32_t(probability * RAND_MAX);
|
f->probability = probability * static_cast<double>(zeek::max_random());
|
||||||
auto prev = static_cast<Filter*>(src_filter.Insert(src, 128, f));
|
auto prev = static_cast<Filter*>(src_filter.Insert(src, 128, f));
|
||||||
delete prev;
|
delete prev;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ void PacketFilter::AddSrc(zeek::Val* src, uint32_t tcp_flags, double probability
|
||||||
{
|
{
|
||||||
Filter* f = new Filter;
|
Filter* f = new Filter;
|
||||||
f->tcp_flags = tcp_flags;
|
f->tcp_flags = tcp_flags;
|
||||||
f->probability = uint32_t(probability * RAND_MAX);
|
f->probability = probability * static_cast<double>(zeek::max_random());
|
||||||
auto prev = static_cast<Filter*>(src_filter.Insert(src, f));
|
auto prev = static_cast<Filter*>(src_filter.Insert(src, f));
|
||||||
delete prev;
|
delete prev;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ void PacketFilter::AddDst(const IPAddr& dst, uint32_t tcp_flags, double probabil
|
||||||
{
|
{
|
||||||
Filter* f = new Filter;
|
Filter* f = new Filter;
|
||||||
f->tcp_flags = tcp_flags;
|
f->tcp_flags = tcp_flags;
|
||||||
f->probability = uint32_t(probability * RAND_MAX);
|
f->probability = probability * static_cast<double>(zeek::max_random());
|
||||||
auto prev = static_cast<Filter*>(dst_filter.Insert(dst, 128, f));
|
auto prev = static_cast<Filter*>(dst_filter.Insert(dst, 128, f));
|
||||||
delete prev;
|
delete prev;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ void PacketFilter::AddDst(zeek::Val* dst, uint32_t tcp_flags, double probability
|
||||||
{
|
{
|
||||||
Filter* f = new Filter;
|
Filter* f = new Filter;
|
||||||
f->tcp_flags = tcp_flags;
|
f->tcp_flags = tcp_flags;
|
||||||
f->probability = uint32_t(probability * RAND_MAX);
|
f->probability = probability * static_cast<double>(zeek::max_random());
|
||||||
auto prev = static_cast<Filter*>(dst_filter.Insert(dst, f));
|
auto prev = static_cast<Filter*>(dst_filter.Insert(dst, f));
|
||||||
delete prev;
|
delete prev;
|
||||||
}
|
}
|
||||||
|
@ -113,5 +113,5 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint32_t(zeek::random_number()) < f.probability;
|
return zeek::random_number() < f.probability;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
private:
|
private:
|
||||||
struct Filter {
|
struct Filter {
|
||||||
uint32_t tcp_flags;
|
uint32_t tcp_flags;
|
||||||
uint32_t probability;
|
double probability;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DeleteFilter(void* data);
|
static void DeleteFilter(void* data);
|
||||||
|
|
10
src/util.cc
10
src/util.cc
|
@ -1183,13 +1183,21 @@ bool have_random_seed()
|
||||||
return bro_rand_determistic;
|
return bro_rand_determistic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t zeek_prng_mod = 2147483647;
|
||||||
|
constexpr uint32_t zeek_prng_max = zeek_prng_mod - 1;
|
||||||
|
|
||||||
|
long int zeek::max_random()
|
||||||
|
{
|
||||||
|
return bro_rand_determistic ? zeek_prng_max : RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
long int zeek::prng(long int state)
|
long int zeek::prng(long int state)
|
||||||
{
|
{
|
||||||
// Use our own simple linear congruence PRNG to make sure we are
|
// Use our own simple linear congruence PRNG to make sure we are
|
||||||
// predictable across platforms. (Lehmer RNG, Schrage's method)
|
// predictable across platforms. (Lehmer RNG, Schrage's method)
|
||||||
// Note: the choice of "long int" storage type for the state is mostly
|
// Note: the choice of "long int" storage type for the state is mostly
|
||||||
// for parity with the possible return values of random().
|
// for parity with the possible return values of random().
|
||||||
constexpr uint32_t m = 2147483647;
|
constexpr uint32_t m = zeek_prng_mod;
|
||||||
constexpr uint32_t a = 16807;
|
constexpr uint32_t a = 16807;
|
||||||
constexpr uint32_t q = m / a;
|
constexpr uint32_t q = m / a;
|
||||||
constexpr uint32_t r = m % a;
|
constexpr uint32_t r = m % a;
|
||||||
|
|
|
@ -604,7 +604,14 @@ long int prng(long int state);
|
||||||
* Wrapper for system random() in the default case, but when running in
|
* Wrapper for system random() in the default case, but when running in
|
||||||
* deterministic mode, uses the platform-independent zeek::prng()
|
* deterministic mode, uses the platform-independent zeek::prng()
|
||||||
* to obtain consistent results since implementations of rand() may vary.
|
* to obtain consistent results since implementations of rand() may vary.
|
||||||
|
* @return A value in the range [0, zeek::max_random()].
|
||||||
*/
|
*/
|
||||||
long int random_number();
|
long int random_number();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The maximum value that can be returned from zeek::random_number().
|
||||||
|
* When not using deterministic-mode, this is always equivalent to RAND_MAX.
|
||||||
|
*/
|
||||||
|
long int max_random();
|
||||||
|
|
||||||
} // namespace zeek
|
} // namespace zeek
|
||||||
|
|
|
@ -930,7 +930,7 @@ function hrw_weight%(key_digest: count, site_id: count%): count
|
||||||
## provided by the OS.
|
## provided by the OS.
|
||||||
function rand%(max: count%): count
|
function rand%(max: count%): count
|
||||||
%{
|
%{
|
||||||
auto result = bro_uint_t(double(max) * double(zeek::random_number()) / (RAND_MAX + 1.0));
|
auto result = bro_uint_t(double(max) * double(zeek::random_number()) / (zeek::max_random() + 1.0));
|
||||||
return zeek::val_mgr->Count(result);
|
return zeek::val_mgr->Count(result);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ std::string Foo::RandomString(const int len)
|
||||||
// zeek::random_number() is not thread-safe; as we are only using one simultaneous thread
|
// zeek::random_number() is not thread-safe; as we are only using one simultaneous thread
|
||||||
// here, this should not matter in this case. If this test ever starts showing
|
// here, this should not matter in this case. If this test ever starts showing
|
||||||
// random errors, this might be the culprit.
|
// random errors, this might be the culprit.
|
||||||
s[i] = values[zeek::random_number() / (RAND_MAX / sizeof(values))];
|
s[i] = values[zeek::random_number() / (zeek::max_random() / sizeof(values))];
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue