Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/file_util.h" | 15 #include "base/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 "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 19 |
| 20 using std::nothrow; | 20 using std::nothrow; |
| 21 using std::numeric_limits; | 21 using std::numeric_limits; |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // This function acts as a compiler optimization barrier. We use it to | |
| 26 // prevent the compiler from making an expression a compile-time constant. | |
| 27 // We also use it so that the compiler doesn't discard certain return values | |
| 28 // as something we don't need (see the comment with calloc below). | |
| 29 template <typename Type> | |
| 30 Type HideValueFromCompiler(volatile Type value) { | |
| 31 return value; | |
| 32 } | |
| 33 | |
| 25 // Check that we can not allocate a memory range that cannot be indexed | 34 // Check that we can not allocate a memory range that cannot be indexed |
| 26 // via an int. This is used to mitigate vulnerabilities in libraries that use | 35 // via an int. This is used to mitigate vulnerabilities in libraries that use |
| 27 // int instead of size_t. | 36 // int instead of size_t. |
| 28 // See crbug.com/169327. | 37 // See crbug.com/169327. |
| 29 | 38 |
| 30 // - NO_TCMALLOC because we only patched tcmalloc | 39 // - NO_TCMALLOC because we only patched tcmalloc |
| 31 // - ADDRESS_SANITIZER because it has its own memory allocator | 40 // - ADDRESS_SANITIZER because it has its own memory allocator |
| 32 // - IOS does not seem to honor nothrow in new properly | 41 // - IOS does not seem to honor nothrow in new properly |
| 33 // - OS_MACOSX does not use tcmalloc | 42 // - OS_MACOSX does not use tcmalloc |
| 34 #if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \ | 43 #if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \ |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 54 } | 63 } |
| 55 | 64 |
| 56 // Fake test that allow to know the state of TCMalloc by looking at bots. | 65 // Fake test that allow to know the state of TCMalloc by looking at bots. |
| 57 TEST(SecurityTest, ALLOC_TEST(IsTCMallocDynamicallyBypassed)) { | 66 TEST(SecurityTest, ALLOC_TEST(IsTCMallocDynamicallyBypassed)) { |
| 58 printf("Malloc is dynamically bypassed: %s\n", | 67 printf("Malloc is dynamically bypassed: %s\n", |
| 59 IsTcMallocBypassed() ? "yes." : "no."); | 68 IsTcMallocBypassed() ? "yes." : "no."); |
| 60 } | 69 } |
| 61 | 70 |
| 62 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) { | 71 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) { |
| 63 if (!IsTcMallocBypassed()) { | 72 if (!IsTcMallocBypassed()) { |
| 64 scoped_ptr<char, base::FreeDeleter> | 73 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>( |
| 65 ptr(static_cast<char*>(malloc(kTooBigAllocSize))); | 74 HideValueFromCompiler(malloc(kTooBigAllocSize)))); |
| 66 ASSERT_TRUE(ptr == NULL); | 75 ASSERT_TRUE(ptr == NULL); |
|
awong
2013/02/05 22:42:22
drive-by nit: this would be cleaner as ASSERT_TRUE
jln (very slow on Chromium)
2013/02/06 00:05:01
This used to not work with scoped ptr. In general
| |
| 67 } | 76 } |
| 68 } | 77 } |
| 69 | 78 |
| 70 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) { | 79 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) { |
| 71 if (!IsTcMallocBypassed()) { | 80 if (!IsTcMallocBypassed()) { |
| 72 scoped_ptr<char, base::FreeDeleter> | 81 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>( |
| 73 ptr(static_cast<char*>(calloc(kTooBigAllocSize, 1))); | 82 HideValueFromCompiler(calloc(kTooBigAllocSize, 1)))); |
| 74 ASSERT_TRUE(ptr == NULL); | 83 ASSERT_TRUE(ptr == NULL); |
| 75 } | 84 } |
| 76 } | 85 } |
| 77 | 86 |
| 78 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsRealloc)) { | 87 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsRealloc)) { |
| 79 if (!IsTcMallocBypassed()) { | 88 if (!IsTcMallocBypassed()) { |
| 80 char* orig_ptr = static_cast<char*>(malloc(1)); | 89 char* orig_ptr = static_cast<char*>(malloc(1)); |
| 81 ASSERT_TRUE(orig_ptr != NULL); | 90 ASSERT_TRUE(orig_ptr != NULL); |
| 82 scoped_ptr<char, base::FreeDeleter> | 91 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>( |
| 83 ptr(static_cast<char*>(realloc(orig_ptr, kTooBigAllocSize))); | 92 HideValueFromCompiler(realloc(orig_ptr, kTooBigAllocSize)))); |
| 84 ASSERT_TRUE(ptr == NULL); | 93 ASSERT_TRUE(ptr == NULL); |
| 85 // If realloc() did not succeed, we need to free orig_ptr. | 94 // If realloc() did not succeed, we need to free orig_ptr. |
| 86 free(orig_ptr); | 95 free(orig_ptr); |
| 87 } | 96 } |
| 88 } | 97 } |
| 89 | 98 |
| 90 typedef struct { | 99 typedef struct { |
| 91 char large_array[kTooBigAllocSize]; | 100 char large_array[kTooBigAllocSize]; |
| 92 } VeryLargeStruct; | 101 } VeryLargeStruct; |
| 93 | 102 |
| 94 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) { | 103 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) { |
| 95 if (!IsTcMallocBypassed()) { | 104 if (!IsTcMallocBypassed()) { |
| 96 scoped_ptr<VeryLargeStruct> ptr(new (nothrow) VeryLargeStruct); | 105 scoped_ptr<VeryLargeStruct> ptr( |
| 106 HideValueFromCompiler(new (nothrow) VeryLargeStruct)); | |
| 97 ASSERT_TRUE(ptr == NULL); | 107 ASSERT_TRUE(ptr == NULL); |
| 98 } | 108 } |
| 99 } | 109 } |
| 100 | 110 |
| 101 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) { | 111 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) { |
| 102 if (!IsTcMallocBypassed()) { | 112 if (!IsTcMallocBypassed()) { |
| 103 scoped_ptr<char[]> ptr(new (nothrow) char[kTooBigAllocSize]); | 113 scoped_ptr<char[]> ptr( |
| 114 HideValueFromCompiler(new (nothrow) char[kTooBigAllocSize])); | |
| 104 ASSERT_TRUE(ptr == NULL); | 115 ASSERT_TRUE(ptr == NULL); |
| 105 } | 116 } |
| 106 } | 117 } |
| 107 | 118 |
| 108 // The tests bellow check for overflows in new[] and calloc(). | 119 // The tests bellow check for overflows in new[] and calloc(). |
| 109 | 120 |
| 110 #if defined(OS_IOS) || defined(OS_WIN) | 121 #if defined(OS_IOS) || defined(OS_WIN) |
| 111 #define DISABLE_ON_IOS_AND_WIN(function) DISABLED_##function | 122 #define DISABLE_ON_IOS_AND_WIN(function) DISABLED_##function |
| 112 #else | 123 #else |
| 113 #define DISABLE_ON_IOS_AND_WIN(function) function | 124 #define DISABLE_ON_IOS_AND_WIN(function) function |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 130 printf("Platform has overflow: %s\n", | 141 printf("Platform has overflow: %s\n", |
| 131 !overflow_detected ? "yes." : "no."); | 142 !overflow_detected ? "yes." : "no."); |
| 132 #else | 143 #else |
| 133 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT | 144 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT |
| 134 // aren't). | 145 // aren't). |
| 135 EXPECT_TRUE(overflow_detected); | 146 EXPECT_TRUE(overflow_detected); |
| 136 #endif | 147 #endif |
| 137 } | 148 } |
| 138 } | 149 } |
| 139 | 150 |
| 140 // This function acts as a compiler optimization barrier. We use it to | |
| 141 // prevent the compiler from making an expression a compile-time constant. | |
| 142 // We also use it so that the compiler doesn't discard certain return values | |
| 143 // as something we don't need (see the comment with calloc below). | |
| 144 template <typename Type> | |
| 145 Type HideValueFromCompiler(volatile Type value) { | |
| 146 return value; | |
| 147 } | |
| 148 | |
| 149 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows. | 151 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows. |
| 150 // IOS doesn't honor nothrow, so disable the test there. | 152 // IOS doesn't honor nothrow, so disable the test there. |
| 151 // Disable on Windows, we suspect some are failing because of it. | 153 // Disable on Windows, we suspect some are failing because of it. |
| 152 TEST(SecurityTest, DISABLE_ON_IOS_AND_WIN(NewOverflow)) { | 154 TEST(SecurityTest, DISABLE_ON_IOS_AND_WIN(NewOverflow)) { |
| 153 const size_t kArraySize = 4096; | 155 const size_t kArraySize = 4096; |
| 154 // We want something "dynamic" here, so that the compiler doesn't | 156 // We want something "dynamic" here, so that the compiler doesn't |
| 155 // immediately reject crazy arrays. | 157 // immediately reject crazy arrays. |
| 156 const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize); | 158 const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize); |
| 157 // numeric_limits are still not constexpr until we switch to C++11, so we | 159 // numeric_limits are still not constexpr until we switch to C++11, so we |
| 158 // use an ugly cast. | 160 // use an ugly cast. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 return; // Test passes. | 247 return; // Test passes. |
| 246 } | 248 } |
| 247 } | 249 } |
| 248 } | 250 } |
| 249 ASSERT_TRUE(false); // NOTREACHED(); | 251 ASSERT_TRUE(false); // NOTREACHED(); |
| 250 } | 252 } |
| 251 | 253 |
| 252 #endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) | 254 #endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) |
| 253 | 255 |
| 254 } // namespace | 256 } // namespace |
| OLD | NEW |