Index: base/security_unittest.cc |
diff --git a/base/security_unittest.cc b/base/security_unittest.cc |
index ffb92024ca0fcf12bb565d907b2b2498048a1de9..93ebe37d6c237226bf87be3e19da9168e734ae51 100644 |
--- a/base/security_unittest.cc |
+++ b/base/security_unittest.cc |
@@ -2,13 +2,17 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <fcntl.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
+#include <sys/stat.h> |
+#include <sys/types.h> |
#include <algorithm> |
#include <limits> |
+#include "base/file_util.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -192,4 +196,56 @@ TEST(SecurityTest, DISABLE_ON_ASAN(CallocOverflow)) { |
} |
} |
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) |
+// Useful for debugging. |
+void PrintProcSelfMaps() { |
+ int fd = open("/proc/self/maps", O_RDONLY); |
+ file_util::ScopedFD fd_closer(&fd); |
+ ASSERT_GE(fd, 0); |
+ char buffer[1<<13]; |
+ int ret; |
+ ret = read(fd, buffer, sizeof(buffer) - 1); |
+ ASSERT_GT(ret, 0); |
+ buffer[ret - 1] = 0; |
+ fprintf(stdout, "%s\n", buffer); |
+} |
+ |
+// Check if TCMalloc uses an underlying random memory allocator. |
+TEST(SecurityTest, ALLOC_TEST(RandomMemoryAllocations)) { |
+ if (IsTcMallocBypassed()) |
+ return; |
+ // Two successive calls to mmap() have roughly one chance out of 2^6 to be |
+ // detected as having the same order. With 32 allocations, we see ~16 that |
jar (doing other things)
2013/01/30 17:20:48
I didn't understand the argument.
Down below, you
jln (very slow on Chromium)
2013/01/30 20:11:33
6 comes from the smallest mask that we use in the
|
+ // trigger a call to mmap, so the chances of this test flaking is roughly |
jar (doing other things)
2013/01/30 17:20:48
I'm not sure why these calls would trigger mmap ca
jln (very slow on Chromium)
2013/01/30 20:11:33
I did check the number of mmaps by adding some ins
|
+ // 2^-(6*15), i.e. virtually impossible. |
+ const int kAllocNumber = 32; |
+ bool is_contiguous = true; |
+ // Make kAllocNumber successive allocations of growing size and compare the |
+ // successive pointers to detect adjacent mappings. We grow the size because |
+ // TCMalloc can sometimes over-allocate. |
+ scoped_ptr<char, base::FreeDeleter> ptr[kAllocNumber]; |
+ for (int i = 0; i < kAllocNumber; ++i) { |
+ // Grow the Malloc size slightly sub-exponentially. |
+ const size_t kMallocSize = 1 << (12 + (i>>1)); |
+ ptr[i].reset(static_cast<char*>(malloc(kMallocSize))); |
+ ASSERT_TRUE(ptr[i] != NULL); |
+ if (i > 0) { |
+ // Without mmap randomization, the two high order nibbles |
+ // of a 47 bits userland address address will be identical. |
+ const uintptr_t kHighOrderMask = 0xff0000000000ULL; |
+ bool pointer_have_same_high_order = |
+ (reinterpret_cast<size_t>(ptr[i].get()) & kHighOrderMask) == |
+ (reinterpret_cast<size_t>(ptr[i - 1].get()) & kHighOrderMask); |
+ if (!pointer_have_same_high_order) { |
+ // PrintProcSelfMaps(); |
+ is_contiguous = false; |
jar (doing other things)
2013/01/30 17:20:48
This test will break out of this loop (causing the
jln (very slow on Chromium)
2013/01/30 20:11:33
You make good points, but I am quite happy with wh
|
+ break; |
jar (doing other things)
2013/01/30 17:35:29
nit: if you keep this test as is, it is much more
jln (very slow on Chromium)
2013/01/30 20:11:33
Done.
|
+ } |
+ } |
+ } |
+ ASSERT_FALSE(is_contiguous); |
+} |
+ |
+#endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) |
+ |
} // namespace |