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

Unified Diff: base/security_unittest.cc

Issue 12220107: Base: account for calloc aborting in security unittests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test for GTEST_HAS_DEATH_TEST. Created 7 years, 10 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/security_unittest.cc
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index 59a3ddd6ca51bc00452c98cc426436ec167050aa..14540032f9dbf425ffb0d8ef57ce1a5d0beabc4a 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -37,20 +37,15 @@ Type HideValueFromCompiler(volatile Type value) {
return value;
}
-// Check that we can not allocate a memory range that cannot be indexed
-// via an int. This is used to mitigate vulnerabilities in libraries that use
-// int instead of size_t.
-// See crbug.com/169327.
-
-// - NO_TCMALLOC because we only patched tcmalloc
+// - NO_TCMALLOC (should be defined if we compile with linux_use_tcmalloc=0)
// - ADDRESS_SANITIZER because it has its own memory allocator
-// - IOS does not seem to honor nothrow in new properly
+// - IOS does not use tcmalloc
// - OS_MACOSX does not use tcmalloc
#if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \
!defined(OS_IOS) && !defined(OS_MACOSX)
- #define ALLOC_TEST(function) function
+ #define TCMALLOC_TEST(function) function
#else
- #define ALLOC_TEST(function) DISABLED_##function
+ #define TCMALLOC_TEST(function) DISABLED_##function
#endif
// TODO(jln): switch to std::numeric_limits<int>::max() when we switch to
@@ -68,13 +63,28 @@ bool IsTcMallocBypassed() {
return false;
}
+bool CallocDiesOnOOM() {
+// The wrapper function in base/process_util_linux.cc that is used when we
+// compile without TCMalloc will just die on OOM instead of returning NULL.
+#if defined(OS_LINUX) && defined(NO_TCMALLOC)
+ return true;
+#else
+ return false;
+#endif
+}
+
// Fake test that allow to know the state of TCMalloc by looking at bots.
-TEST(SecurityTest, ALLOC_TEST(IsTCMallocDynamicallyBypassed)) {
+TEST(SecurityTest, TCMALLOC_TEST(IsTCMallocDynamicallyBypassed)) {
printf("Malloc is dynamically bypassed: %s\n",
IsTcMallocBypassed() ? "yes." : "no.");
}
-TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) {
+// The MemoryAllocationRestrictions* tests test that we can not allocate a
+// memory range that cannot be indexed via an int. This is used to mitigate
+// vulnerabilities in libraries that use int instead of size_t. See
+// crbug.com/169327.
+
+TEST(SecurityTest, TCMALLOC_TEST(MemoryAllocationRestrictionsMalloc)) {
if (!IsTcMallocBypassed()) {
scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
HideValueFromCompiler(malloc(kTooBigAllocSize))));
@@ -82,7 +92,7 @@ TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) {
}
}
-TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) {
+TEST(SecurityTest, TCMALLOC_TEST(MemoryAllocationRestrictionsCalloc)) {
if (!IsTcMallocBypassed()) {
scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
HideValueFromCompiler(calloc(kTooBigAllocSize, 1))));
@@ -90,7 +100,7 @@ TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) {
}
}
-TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsRealloc)) {
+TEST(SecurityTest, TCMALLOC_TEST(MemoryAllocationRestrictionsRealloc)) {
if (!IsTcMallocBypassed()) {
char* orig_ptr = static_cast<char*>(malloc(1));
ASSERT_TRUE(orig_ptr);
@@ -106,7 +116,7 @@ typedef struct {
char large_array[kTooBigAllocSize];
} VeryLargeStruct;
-TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) {
+TEST(SecurityTest, TCMALLOC_TEST(MemoryAllocationRestrictionsNew)) {
if (!IsTcMallocBypassed()) {
scoped_ptr<VeryLargeStruct> ptr(
HideValueFromCompiler(new (nothrow) VeryLargeStruct));
@@ -114,7 +124,7 @@ TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) {
}
}
-TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) {
+TEST(SecurityTest, TCMALLOC_TEST(MemoryAllocationRestrictionsNewArray)) {
if (!IsTcMallocBypassed()) {
scoped_ptr<char[]> ptr(
HideValueFromCompiler(new (nothrow) char[kTooBigAllocSize]));
@@ -184,27 +194,32 @@ TEST(SecurityTest, DISABLE_ON_IOS_AND_WIN(NewOverflow)) {
}
#endif
+// Call calloc(), eventually free the memory and return whether or not
+// calloc() did succeed.
+bool CallocReturnsNull(size_t nmemb, size_t size) {
+ scoped_ptr<char, base::FreeDeleter> array_pointer(
+ static_cast<char*>(calloc(nmemb, size)));
+ // We need the call to HideValueFromCompiler(): we have seen LLVM
+ // optimize away the call to calloc() entirely and assume
+ // the pointer to not be NULL.
+ return HideValueFromCompiler(array_pointer.get()) == NULL;
+}
+
// Test if calloc() can overflow. Disable on ASAN for now since the
-// overflow seems present there.
+// overflow seems present there (crbug.com/175554).
TEST(SecurityTest, DISABLE_ON_ASAN(CallocOverflow)) {
const size_t kArraySize = 4096;
const size_t kMaxSizeT = numeric_limits<size_t>::max();
const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
- {
- scoped_ptr<char> array_pointer(
- static_cast<char*>(calloc(kArraySize, kArraySize2)));
- // We need the call to HideValueFromCompiler(): we have seen LLVM
- // optimize away the call to calloc() entirely and assume
- // the pointer to not be NULL.
- EXPECT_TRUE(HideValueFromCompiler(array_pointer.get()) == NULL);
- }
- {
- scoped_ptr<char> array_pointer(
- static_cast<char*>(calloc(kArraySize2, kArraySize)));
- // We need the call to HideValueFromCompiler(): we have seen LLVM
- // optimize away the call to calloc() entirely and assume
- // the pointer to not be NULL.
- EXPECT_TRUE(HideValueFromCompiler(array_pointer.get()) == NULL);
+ if (!CallocDiesOnOOM()) {
+ EXPECT_TRUE(CallocReturnsNull(kArraySize, kArraySize2));
+ EXPECT_TRUE(CallocReturnsNull(kArraySize2, kArraySize));
+ } else {
+ // It's also ok for calloc to just terminate the process.
+#if defined(GTEST_HAS_DEATH_TEST)
+ EXPECT_DEATH(CallocReturnsNull(kArraySize, kArraySize2), "");
+ EXPECT_DEATH(CallocReturnsNull(kArraySize2, kArraySize), "");
+#endif // GTEST_HAS_DEATH_TEST
}
}
@@ -230,7 +245,7 @@ bool ArePointersToSameArea(void* ptr1, void* ptr2, size_t size) {
}
// Check if TCMalloc uses an underlying random memory allocator.
-TEST(SecurityTest, ALLOC_TEST(RandomMemoryAllocations)) {
+TEST(SecurityTest, TCMALLOC_TEST(RandomMemoryAllocations)) {
if (IsTcMallocBypassed())
return;
size_t kPageSize = 4096; // We support x86_64 only.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698