Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(751)

Side by Side Diff: base/security_unittest.cc

Issue 1452063005: Fixing base unittests impacted by Debug ASAN (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/message_loop/message_pump_libevent_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <fcntl.h> 5 #include <fcntl.h>
6 #include <stdio.h> 6 #include <stdio.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <limits> 13 #include <limits>
14 14
15 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
20 20
21 #if defined(OS_POSIX) 21 #if defined(OS_POSIX)
22 #include <sys/mman.h> 22 #include <sys/mman.h>
23 #include <unistd.h> 23 #include <unistd.h>
24 #endif 24 #endif
25 25
26 #if defined(OS_WIN)
27 #include <new.h>
28 #endif
29
30 using std::nothrow; 26 using std::nothrow;
31 using std::numeric_limits; 27 using std::numeric_limits;
32 28
33 namespace { 29 namespace {
34 30
35 #if defined(OS_WIN)
36 // This is a permitted size but exhausts memory pretty quickly.
37 const size_t kLargePermittedAllocation = 0x7FFFE000;
38
39 int OnNoMemory(size_t) {
40 _exit(1);
41 }
42
43 void ExhaustMemoryWithMalloc() {
44 for (;;) {
45 // Without the |volatile|, clang optimizes away the allocation.
46 void* volatile buf = malloc(kLargePermittedAllocation);
47 if (!buf)
48 break;
49 }
50 }
51
52 void ExhaustMemoryWithRealloc() {
53 size_t size = kLargePermittedAllocation;
54 void* buf = malloc(size);
55 if (!buf)
56 return;
57 for (;;) {
58 size += kLargePermittedAllocation;
59 void* new_buf = realloc(buf, size);
60 if (!buf)
61 break;
62 buf = new_buf;
63 }
64 }
65 #endif
66
67 // This function acts as a compiler optimization barrier. We use it to 31 // This function acts as a compiler optimization barrier. We use it to
68 // prevent the compiler from making an expression a compile-time constant. 32 // prevent the compiler from making an expression a compile-time constant.
69 // We also use it so that the compiler doesn't discard certain return values 33 // We also use it so that the compiler doesn't discard certain return values
70 // as something we don't need (see the comment with calloc below). 34 // as something we don't need (see the comment with calloc below).
71 template <typename Type> 35 template <typename Type>
72 NOINLINE Type HideValueFromCompiler(volatile Type value) { 36 NOINLINE Type HideValueFromCompiler(volatile Type value) {
73 #if defined(__GNUC__) 37 #if defined(__GNUC__)
74 // In a GCC compatible compiler (GCC or Clang), make this compiler barrier 38 // In a GCC compatible compiler (GCC or Clang), make this compiler barrier
75 // more robust than merely using "volatile". 39 // more robust than merely using "volatile".
76 __asm__ volatile ("" : "+r" (value)); 40 __asm__ volatile ("" : "+r" (value));
77 #endif // __GNUC__ 41 #endif // __GNUC__
78 return value; 42 return value;
79 } 43 }
80 44
81 // Tcmalloc and Windows allocator shim support setting malloc limits. 45 // Tcmalloc and Windows allocator shim support setting malloc limits.
82 // - NO_TCMALLOC (should be defined if compiled with use_allocator!="tcmalloc") 46 // - NO_TCMALLOC (should be defined if compiled with use_allocator!="tcmalloc")
83 // - ADDRESS_SANITIZER and SYZYASAN because they have their own memory allocator 47 // - ADDRESS_SANITIZER and SYZYASAN because they have their own memory allocator
84 // - IOS does not use tcmalloc 48 // - IOS does not use tcmalloc
85 // - OS_MACOSX does not use tcmalloc 49 // - OS_MACOSX does not use tcmalloc
86 // - Windows allocator shim defines ALLOCATOR_SHIM 50 // - Windows allocator shim defines ALLOCATOR_SHIM
87 #if (!defined(NO_TCMALLOC) || defined(ALLOCATOR_SHIM)) && \ 51 #if (!defined(NO_TCMALLOC) || defined(ALLOCATOR_SHIM)) && \
88 !defined(ADDRESS_SANITIZER) && !defined(OS_IOS) && !defined(OS_MACOSX) && \ 52 !defined(ADDRESS_SANITIZER) && !defined(OS_IOS) && !defined(OS_MACOSX) && \
89 !defined(SYZYASAN) 53 !defined(SYZYASAN)
90 #define MALLOC_OVERFLOW_TEST(function) function 54 #define MALLOC_OVERFLOW_TEST(function) function
91 #else 55 #else
92 #define MALLOC_OVERFLOW_TEST(function) DISABLED_##function 56 #define MALLOC_OVERFLOW_TEST(function) DISABLED_##function
93 #endif 57 #endif
94 58
95 // TODO(jln): switch to std::numeric_limits<int>::max() when we switch to 59 #if defined(OS_LINUX) && defined(__x86_64__)
96 // C++11.
97 const size_t kTooBigAllocSize = INT_MAX;
98
99 // Detect runtime TCMalloc bypasses. 60 // Detect runtime TCMalloc bypasses.
100 bool IsTcMallocBypassed() { 61 bool IsTcMallocBypassed() {
101 #if defined(OS_LINUX)
102 // This should detect a TCMalloc bypass from Valgrind. 62 // This should detect a TCMalloc bypass from Valgrind.
103 char* g_slice = getenv("G_SLICE"); 63 char* g_slice = getenv("G_SLICE");
104 if (g_slice && !strcmp(g_slice, "always-malloc")) 64 if (g_slice && !strcmp(g_slice, "always-malloc"))
105 return true; 65 return true;
106 #endif
107 return false; 66 return false;
108 } 67 }
109
110 bool CallocDiesOnOOM() {
111 // The sanitizers' calloc dies on OOM instead of returning NULL.
112 // The wrapper function in base/process_util_linux.cc that is used when we
113 // compile without TCMalloc will just die on OOM instead of returning NULL.
114 #if defined(ADDRESS_SANITIZER) || \
115 defined(MEMORY_SANITIZER) || \
116 defined(THREAD_SANITIZER) || \
117 (defined(OS_LINUX) && defined(NO_TCMALLOC))
118 return true;
119 #else
120 return false;
121 #endif
122 }
123
124 // Fake test that allow to know the state of TCMalloc by looking at bots.
125 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(IsTCMallocDynamicallyBypassed)) {
126 printf("Malloc is dynamically bypassed: %s\n",
127 IsTcMallocBypassed() ? "yes." : "no.");
128 }
129
130 // The MemoryAllocationRestrictions* tests test that we can not allocate a
131 // memory range that cannot be indexed via an int. This is used to mitigate
132 // vulnerabilities in libraries that use int instead of size_t. See
133 // crbug.com/169327.
134
135 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationRestrictionsMalloc)) {
136 if (!IsTcMallocBypassed()) {
137 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
138 HideValueFromCompiler(malloc(kTooBigAllocSize))));
139 ASSERT_TRUE(!ptr);
140 }
141 }
142
143 #if defined(GTEST_HAS_DEATH_TEST) && defined(OS_WIN)
144 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationMallocDeathTest)) {
145 _set_new_handler(&OnNoMemory);
146 _set_new_mode(1);
147 {
148 scoped_ptr<char, base::FreeDeleter> ptr;
149 EXPECT_DEATH(ptr.reset(static_cast<char*>(
150 HideValueFromCompiler(malloc(kTooBigAllocSize)))),
151 "");
152 ASSERT_TRUE(!ptr);
153 }
154 _set_new_handler(NULL);
155 _set_new_mode(0);
156 }
157
158 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationExhaustDeathTest)) {
159 _set_new_handler(&OnNoMemory);
160 _set_new_mode(1);
161 {
162 ASSERT_DEATH(ExhaustMemoryWithMalloc(), "");
163 }
164 _set_new_handler(NULL);
165 _set_new_mode(0);
166 }
167
168 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryReallocationExhaustDeathTest)) {
169 _set_new_handler(&OnNoMemory);
170 _set_new_mode(1);
171 {
172 ASSERT_DEATH(ExhaustMemoryWithRealloc(), "");
173 }
174 _set_new_handler(NULL);
175 _set_new_mode(0);
176 }
177 #endif 68 #endif
178 69
179 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationRestrictionsCalloc)) {
180 if (!IsTcMallocBypassed()) {
181 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
182 HideValueFromCompiler(calloc(kTooBigAllocSize, 1))));
183 ASSERT_TRUE(!ptr);
184 }
185 }
186
187 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationRestrictionsRealloc)) {
188 if (!IsTcMallocBypassed()) {
189 char* orig_ptr = static_cast<char*>(malloc(1));
190 ASSERT_TRUE(orig_ptr);
191 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
192 HideValueFromCompiler(realloc(orig_ptr, kTooBigAllocSize))));
193 ASSERT_TRUE(!ptr);
194 // If realloc() did not succeed, we need to free orig_ptr.
195 free(orig_ptr);
196 }
197 }
198
199 typedef struct {
200 char large_array[kTooBigAllocSize];
201 } VeryLargeStruct;
202
203 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationRestrictionsNew)) {
204 if (!IsTcMallocBypassed()) {
205 scoped_ptr<VeryLargeStruct> ptr(
206 HideValueFromCompiler(new (nothrow) VeryLargeStruct));
207 ASSERT_TRUE(!ptr);
208 }
209 }
210
211 #if defined(GTEST_HAS_DEATH_TEST) && defined(OS_WIN)
212 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationNewDeathTest)) {
213 _set_new_handler(&OnNoMemory);
214 {
215 scoped_ptr<VeryLargeStruct> ptr;
216 EXPECT_DEATH(
217 ptr.reset(HideValueFromCompiler(new (nothrow) VeryLargeStruct)), "");
218 ASSERT_TRUE(!ptr);
219 }
220 _set_new_handler(NULL);
221 }
222 #endif
223
224 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(MemoryAllocationRestrictionsNewArray)) {
225 if (!IsTcMallocBypassed()) {
226 scoped_ptr<char[]> ptr(
227 HideValueFromCompiler(new (nothrow) char[kTooBigAllocSize]));
228 ASSERT_TRUE(!ptr);
229 }
230 }
231
232 // The tests bellow check for overflows in new[] and calloc().
233
234 // There are platforms where these tests are known to fail. We would like to 70 // There are platforms where these tests are known to fail. We would like to
235 // be able to easily check the status on the bots, but marking tests as 71 // be able to easily check the status on the bots, but marking tests as
236 // FAILS_ is too clunky. 72 // FAILS_ is too clunky.
237 void OverflowTestsSoftExpectTrue(bool overflow_detected) { 73 void OverflowTestsSoftExpectTrue(bool overflow_detected) {
238 if (!overflow_detected) { 74 if (!overflow_detected) {
239 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX) 75 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
240 // Sadly, on Linux, Android, and OSX we don't have a good story yet. Don't 76 // Sadly, on Linux, Android, and OSX we don't have a good story yet. Don't
241 // fail the test, but report. 77 // fail the test, but report.
242 printf("Platform has overflow: %s\n", 78 printf("Platform has overflow: %s\n",
243 !overflow_detected ? "yes." : "no."); 79 !overflow_detected ? "yes." : "no.");
244 #else 80 #else
245 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT 81 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT
246 // aren't). 82 // aren't).
247 EXPECT_TRUE(overflow_detected); 83 EXPECT_TRUE(overflow_detected);
248 #endif 84 #endif
249 } 85 }
250 } 86 }
251 87
252 #if defined(OS_IOS) || defined(OS_WIN) || defined(THREAD_SANITIZER) || defined(O S_MACOSX) 88 #if defined(OS_IOS) || defined(OS_WIN) || defined(ADDRESS_SANITIZER) || defined( THREAD_SANITIZER) || defined(OS_MACOSX)
253 #define MAYBE_NewOverflow DISABLED_NewOverflow 89 #define MAYBE_NewOverflow DISABLED_NewOverflow
254 #else 90 #else
255 #define MAYBE_NewOverflow NewOverflow 91 #define MAYBE_NewOverflow NewOverflow
256 #endif 92 #endif
257 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows. 93 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows.
258 // IOS doesn't honor nothrow, so disable the test there. 94 // IOS doesn't honor nothrow, so disable the test there.
259 // Crashes on Windows Dbg builds, disable there as well. 95 // Crashes on Windows Dbg builds, disable there as well.
260 // Fails on Mac 10.8 http://crbug.com/227092 96 // Fails on Mac 10.8 http://crbug.com/227092
261 TEST(SecurityTest, MAYBE_NewOverflow) { 97 TEST(SecurityTest, MAYBE_NewOverflow) {
262 const size_t kArraySize = 4096; 98 const size_t kArraySize = 4096;
(...skipping 17 matching lines...) Expand all
280 ALLOW_UNUSED_LOCAL(kDynamicArraySize); 116 ALLOW_UNUSED_LOCAL(kDynamicArraySize);
281 #else 117 #else
282 { 118 {
283 scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow) 119 scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow)
284 char[kDynamicArraySize][kArraySize2]); 120 char[kDynamicArraySize][kArraySize2]);
285 OverflowTestsSoftExpectTrue(!array_pointer); 121 OverflowTestsSoftExpectTrue(!array_pointer);
286 } 122 }
287 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) 123 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
288 } 124 }
289 125
290 // Call calloc(), eventually free the memory and return whether or not
291 // calloc() did succeed.
292 bool CallocReturnsNull(size_t nmemb, size_t size) {
293 scoped_ptr<char, base::FreeDeleter> array_pointer(
294 static_cast<char*>(calloc(nmemb, size)));
295 // We need the call to HideValueFromCompiler(): we have seen LLVM
296 // optimize away the call to calloc() entirely and assume the pointer to not
297 // be NULL.
298 return HideValueFromCompiler(array_pointer.get()) == NULL;
299 }
300
301 // Test if calloc() can overflow.
302 TEST(SecurityTest, CallocOverflow) {
303 const size_t kArraySize = 4096;
304 const size_t kMaxSizeT = numeric_limits<size_t>::max();
305 const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
306 if (!CallocDiesOnOOM()) {
307 EXPECT_TRUE(CallocReturnsNull(kArraySize, kArraySize2));
308 EXPECT_TRUE(CallocReturnsNull(kArraySize2, kArraySize));
309 } else {
310 // It's also ok for calloc to just terminate the process.
311 #if defined(GTEST_HAS_DEATH_TEST)
312 EXPECT_DEATH(CallocReturnsNull(kArraySize, kArraySize2), "");
313 EXPECT_DEATH(CallocReturnsNull(kArraySize2, kArraySize), "");
314 #endif // GTEST_HAS_DEATH_TEST
315 }
316 }
317
318 #if defined(OS_LINUX) && defined(__x86_64__) 126 #if defined(OS_LINUX) && defined(__x86_64__)
319 // Check if ptr1 and ptr2 are separated by less than size chars. 127 // Check if ptr1 and ptr2 are separated by less than size chars.
320 bool ArePointersToSameArea(void* ptr1, void* ptr2, size_t size) { 128 bool ArePointersToSameArea(void* ptr1, void* ptr2, size_t size) {
321 ptrdiff_t ptr_diff = reinterpret_cast<char*>(std::max(ptr1, ptr2)) - 129 ptrdiff_t ptr_diff = reinterpret_cast<char*>(std::max(ptr1, ptr2)) -
322 reinterpret_cast<char*>(std::min(ptr1, ptr2)); 130 reinterpret_cast<char*>(std::min(ptr1, ptr2));
323 return static_cast<size_t>(ptr_diff) <= size; 131 return static_cast<size_t>(ptr_diff) <= size;
324 } 132 }
325 133
326 // Check if TCMalloc uses an underlying random memory allocator. 134 // Check if TCMalloc uses an underlying random memory allocator.
327 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(RandomMemoryAllocations)) { 135 TEST(SecurityTest, MALLOC_OVERFLOW_TEST(RandomMemoryAllocations)) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 // kRandomMask, so we use it as an additional detection mechanism. 175 // kRandomMask, so we use it as an additional detection mechanism.
368 const uintptr_t kRandomMask = 0x3fffffffffffULL; 176 const uintptr_t kRandomMask = 0x3fffffffffffULL;
369 bool impossible_random_address = 177 bool impossible_random_address =
370 reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask; 178 reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask;
371 EXPECT_FALSE(impossible_random_address); 179 EXPECT_FALSE(impossible_random_address);
372 } 180 }
373 181
374 #endif // defined(OS_LINUX) && defined(__x86_64__) 182 #endif // defined(OS_LINUX) && defined(__x86_64__)
375 183
376 } // namespace 184 } // namespace
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_libevent_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698