• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)36 uint32_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()47 RandomContext* 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()81 uint32_t RandomValue() {
82   RandomContext* x = GetRandomContext();
83   subtle::SpinLock::Guard guard(x->lock);
84   return RandomValueInternal(x);
85 }
86 
SetMmapSeedForTesting(int64_t seed)87 void 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