diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp --- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp +++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp @@ -99,6 +99,7 @@ else AdjustedSampleRatePlusOne = 2; + initPRNG(); ThreadLocals.NextSampleCounter = (getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1; diff --git a/compiler-rt/lib/gwp_asan/random.h b/compiler-rt/lib/gwp_asan/random.h --- a/compiler-rt/lib/gwp_asan/random.h +++ b/compiler-rt/lib/gwp_asan/random.h @@ -12,6 +12,9 @@ #include namespace gwp_asan { +// Initialise the PRNG, using time and thread ID as the seed. +void initPRNG(); + // xorshift (32-bit output), extremely fast PRNG that uses arithmetic operations // only. Seeded using walltime. uint32_t getRandomUnsigned32(); diff --git a/compiler-rt/lib/gwp_asan/random.cpp b/compiler-rt/lib/gwp_asan/random.cpp --- a/compiler-rt/lib/gwp_asan/random.cpp +++ b/compiler-rt/lib/gwp_asan/random.cpp @@ -11,9 +11,18 @@ #include +// Initialised to UINT32_MAX - 1 so that an uninitialised GWP-ASan results in a +// sample counter of ((UINT32_MAX - 1) % UINT32_MAX) + 1 (i.e. UINT32_MAX). This +// means the sample counter is regenerated as infrequently as possible if +// GWP-ASan is disabled. +GWP_ASAN_TLS_INITIAL_EXEC uint32_t RandomState = UINT32_MAX - 1; + namespace gwp_asan { +void initPRNG() { + RandomState = time(nullptr) + getThreadID(); +} + uint32_t getRandomUnsigned32() { - thread_local uint32_t RandomState = time(nullptr) + getThreadID(); RandomState ^= RandomState << 13; RandomState ^= RandomState >> 17; RandomState ^= RandomState << 5;