1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "third_party/base/allocator/partition_allocator/random.h" 6 7 #include "build/build_config.h" 8 #include "third_party/base/allocator/partition_allocator/spin_lock.h" 9 #include "third_party/base/no_destructor.h" 10 11 #if defined(OS_WIN) 12 #include <windows.h> 13 #else 14 #include <sys/time.h> 15 #include <unistd.h> 16 #endif 17 18 namespace pdfium { 19 namespace base { 20 21 // This is the same PRNG as used by tcmalloc for mapping address randomness; 22 // see http://burtleburtle.net/bob/rand/smallprng.html. 23 struct RandomContext { 24 subtle::SpinLock lock; 25 bool initialized; 26 uint32_t a; 27 uint32_t b; 28 uint32_t c; 29 uint32_t d; 30 }; 31 32 namespace { 33 34 #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) 35 RandomValueInternal(RandomContext * x)36uint32_t RandomValueInternal(RandomContext* x) { 37 uint32_t e = x->a - rot(x->b, 27); 38 x->a = x->b ^ rot(x->c, 17); 39 x->b = x->c + x->d; 40 x->c = x->d + e; 41 x->d = e + x->a; 42 return x->d; 43 } 44 45 #undef rot 46 GetRandomContext()47RandomContext* GetRandomContext() { 48 static NoDestructor<RandomContext> g_random_context; 49 RandomContext* x = g_random_context.get(); 50 subtle::SpinLock::Guard guard(x->lock); 51 if (UNLIKELY(!x->initialized)) { 52 x->initialized = true; 53 char c; 54 uint32_t seed = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&c)); 55 uint32_t pid; 56 uint32_t usec; 57 #if defined(OS_WIN) 58 pid = GetCurrentProcessId(); 59 SYSTEMTIME st; 60 GetSystemTime(&st); 61 usec = static_cast<uint32_t>(st.wMilliseconds * 1000); 62 #else 63 pid = static_cast<uint32_t>(getpid()); 64 struct timeval tv; 65 gettimeofday(&tv, 0); 66 usec = static_cast<uint32_t>(tv.tv_usec); 67 #endif 68 seed ^= pid; 69 seed ^= usec; 70 x->a = 0xf1ea5eed; 71 x->b = x->c = x->d = seed; 72 for (int i = 0; i < 20; ++i) { 73 RandomValueInternal(x); 74 } 75 } 76 return x; 77 } 78 79 } // namespace 80 RandomValue()81uint32_t RandomValue() { 82 RandomContext* x = GetRandomContext(); 83 subtle::SpinLock::Guard guard(x->lock); 84 return RandomValueInternal(x); 85 } 86 SetMmapSeedForTesting(int64_t seed)87void SetMmapSeedForTesting(int64_t seed) { 88 RandomContext* x = GetRandomContext(); 89 subtle::SpinLock::Guard guard(x->lock); 90 x->a = x->b = static_cast<uint32_t>(seed); 91 x->c = x->d = static_cast<uint32_t>(seed >> 32); 92 x->initialized = true; 93 } 94 95 } // namespace base 96 } // namespace pdfium 97