Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
danakj | 51d26a4 | 2024-04-25 14:23:56 | [diff] [blame] | 4 | |
| 5 | #ifdef UNSAFE_BUFFERS_BUILD |
| 6 | // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. |
| 7 | #pragma allow_unsafe_buffers |
| 8 | #endif |
| 9 | |
Arthur Sonzogni | 0844a99 | 2024-12-12 11:36:20 | [diff] [blame] | 10 | #include<array> |
| 11 | |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 12 | // This file contains intentional memory errors, some of which may lead to |
| 13 | // crashes if the test is ran without special memory testing tools. We use these |
| 14 | // errors to verify the sanity of the tools. |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 15 | |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 16 | #include<stddef.h> |
| 17 | |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 18 | #include<atomic> |
| 19 | |
Scott Violet | 4416579 | 2018-02-22 02:08:08 | [diff] [blame] | 20 | #include"base/cfi_buildflags.h" |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 21 | #include"base/debug/asan_invalid_access.h" |
| 22 | #include"base/debug/profiler.h" |
Hans Wennborg | 9f3bb63d | 2020-04-21 11:12:38 | [diff] [blame] | 23 | #include"base/logging.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 24 | #include"base/memory/raw_ptr.h" |
Peter Boström | 54d7f8d | 2024-11-27 23:03:11 | [diff] [blame] | 25 | #include"base/notreached.h" |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 26 | #include"base/sanitizer_buildflags.h" |
brettw@chromium.org | 34b9963 | 2011-01-01 01:01:06 | [diff] [blame] | 27 | #include"base/threading/thread.h" |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 28 | #include"build/build_config.h" |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 29 | #include"testing/gtest/include/gtest/gtest.h" |
Nathaniel Manista | ca9287e7 | 2024-04-02 15:40:57 | [diff] [blame] | 30 | #include"third_party/abseil-cpp/absl/base/dynamic_annotations.h" |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 31 | |
Nico Weber | aa5ce8fa | 2022-05-03 22:56:23 | [diff] [blame] | 32 | #if BUILDFLAG(IS_WIN) |
| 33 | #include<windows.h> |
| 34 | #else |
| 35 | #include<dlfcn.h> |
| 36 | #endif |
| 37 | |
brettw@chromium.org | ce072a7 | 2010-12-31 20:02:16 | [diff] [blame] | 38 | namespace base{ |
| 39 | |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 40 | namespace{ |
| 41 | |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 42 | constuint32_t kMagicValue=42; |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 43 | |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 44 | // Helper for memory accesses that can potentially corrupt memory or cause a |
| 45 | // crash during a native run. |
Sigurdur Asgeirsson | 69d0bcd | 2018-03-29 21:50:51 | [diff] [blame] | 46 | #if defined(ADDRESS_SANITIZER) |
Rohit Rao | 150dc5bb | 2020-07-22 20:43:55 | [diff] [blame] | 47 | #define HARMFUL_ACCESS(action, error_regexp) \ |
| 48 | EXPECT_DEATH_IF_SUPPORTED(action, error_regexp) |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 49 | #elif BUILDFLAG(IS_HWASAN) |
| 50 | #define HARMFUL_ACCESS(action, error_regexp) \ |
| 51 | EXPECT_DEATH(action,"tag-mismatch") |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 52 | #else |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 53 | #define HARMFUL_ACCESS(action, error_regexp) |
| 54 | #define HARMFUL_ACCESS_IS_NOOP |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 55 | #endif |
| 56 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 57 | voidDoReadUninitializedValue(volatilechar* ptr){ |
eugenis@google.com | 43dea19 | 2012-05-16 08:42:08 | [diff] [blame] | 58 | // Comparison with 64 is to prevent clang from optimizing away the |
thakis@chromium.org | 83a13b2 | 2011-09-18 16:39:12 | [diff] [blame] | 59 | // jump -- valgrind only catches jumps and conditional moves, but clang uses |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 60 | // the borrow flag if the condition is just `*ptr == '\0'`. We no longer |
| 61 | // support valgrind, but this constant should be fine to keep as-is. |
eugenis@google.com | 43dea19 | 2012-05-16 08:42:08 | [diff] [blame] | 62 | if(*ptr==64){ |
earthdok@chromium.org | 1e51a96 | 2014-01-16 05:31:41 | [diff] [blame] | 63 | VLOG(1)<<"Uninit condition is true"; |
timurrrr@chromium.org | adf7d80 | 2010-09-23 09:12:37 | [diff] [blame] | 64 | }else{ |
earthdok@chromium.org | 1e51a96 | 2014-01-16 05:31:41 | [diff] [blame] | 65 | VLOG(1)<<"Uninit condition is false"; |
timurrrr@chromium.org | adf7d80 | 2010-09-23 09:12:37 | [diff] [blame] | 66 | } |
| 67 | } |
| 68 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 69 | voidReadUninitializedValue(volatilechar* ptr){ |
earthdok@chromium.org | 1e51a96 | 2014-01-16 05:31:41 | [diff] [blame] | 70 | #if defined(MEMORY_SANITIZER) |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 71 | EXPECT_DEATH(DoReadUninitializedValue(ptr),"use-of-uninitialized-value"); |
earthdok@chromium.org | 1e51a96 | 2014-01-16 05:31:41 | [diff] [blame] | 72 | #else |
| 73 | DoReadUninitializedValue(ptr); |
| 74 | #endif |
| 75 | } |
| 76 | |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 77 | #ifndef HARMFUL_ACCESS_IS_NOOP |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 78 | voidReadValueOutOfArrayBoundsLeft(char* ptr){ |
pkasting@chromium.org | 45b9eba | 2010-10-18 23:57:49 | [diff] [blame] | 79 | char c= ptr[-2]; |
| 80 | VLOG(1)<<"Reading a byte out of bounds: "<< c; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 81 | } |
| 82 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 83 | voidReadValueOutOfArrayBoundsRight(char* ptr,size_t size){ |
pkasting@chromium.org | 45b9eba | 2010-10-18 23:57:49 | [diff] [blame] | 84 | char c= ptr[size+1]; |
| 85 | VLOG(1)<<"Reading a byte out of bounds: "<< c; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 86 | } |
| 87 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 88 | voidWriteValueOutOfArrayBoundsLeft(char* ptr){ |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 89 | ptr[-1]= kMagicValue; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 90 | } |
| 91 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 92 | voidWriteValueOutOfArrayBoundsRight(char* ptr,size_t size){ |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 93 | ptr[size]= kMagicValue; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 94 | } |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 95 | #endif// HARMFUL_ACCESS_IS_NOOP |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 96 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 97 | voidMakeSomeErrors(char* ptr,size_t size){ |
timurrrr@chromium.org | adf7d80 | 2010-09-23 09:12:37 | [diff] [blame] | 98 | ReadUninitializedValue(ptr); |
mithro@mithis.com | e260ebc | 2013-12-18 05:31:33 | [diff] [blame] | 99 | |
Hans Wennborg | 2a3b7f2 | 2022-09-10 19:35:42 | [diff] [blame] | 100 | HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(ptr),"2 bytes before"); |
| 101 | HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(ptr, size),"1 bytes after"); |
| 102 | HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(ptr),"1 bytes before"); |
| 103 | HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(ptr, size),"0 bytes after"); |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 104 | } |
| 105 | |
glider@chromium.org | 66d051bb | 2010-10-14 08:25:54 | [diff] [blame] | 106 | }// namespace |
| 107 | |
Nico Weber | aa5ce8fa | 2022-05-03 22:56:23 | [diff] [blame] | 108 | #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ |
| 109 | defined(MEMORY_SANITIZER)|| defined(THREAD_SANITIZER)|| \ |
| 110 | defined(UNDEFINED_SANITIZER) |
| 111 | // build/sanitizers/sanitizer_options.cc defines symbols like |
| 112 | // __asan_default_options which the sanitizer runtime calls if they exist |
| 113 | // in the executable. If they don't, the sanitizer runtime silently uses an |
| 114 | // internal default value instead. The build puts the symbol |
| 115 | // _sanitizer_options_link_helper (which the sanitizer runtime doesn't know |
| 116 | // about, it's a chrome thing) in that file and then tells the linker that |
| 117 | // that symbol must exist. This causes sanitizer_options.cc to be part of |
| 118 | // our binaries, which in turn makes sure our __asan_default_options are used. |
| 119 | // We had problems with __asan_default_options not being used, so this test |
| 120 | // verifies that _sanitizer_options_link_helper actually makes it into our |
| 121 | // binaries. |
| 122 | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) |
Alison Gale | 81f4f2c7 | 2024-04-22 19:33:31 | [diff] [blame] | 123 | // TODO(crbug.com/40224191): Sanitizer options are currently broken |
Nico Weber | aa5ce8fa | 2022-05-03 22:56:23 | [diff] [blame] | 124 | // on Android. |
Alison Gale | 81f4f2c7 | 2024-04-22 19:33:31 | [diff] [blame] | 125 | // TODO(crbug.com/40223949): __asan_default_options should be used |
Nico Weber | aa5ce8fa | 2022-05-03 22:56:23 | [diff] [blame] | 126 | // on Windows too, but currently isn't. |
| 127 | #define MAYBE_LinksSanitizerOptions DISABLED_LinksSanitizerOptions |
| 128 | #else |
| 129 | #define MAYBE_LinksSanitizerOptionsLinksSanitizerOptions |
| 130 | #endif |
| 131 | TEST(ToolsSanityTest, MAYBE_LinksSanitizerOptions){ |
| 132 | constexprchar kSym[]="_sanitizer_options_link_helper"; |
| 133 | #if BUILDFLAG(IS_WIN) |
| 134 | auto sym=GetProcAddress(GetModuleHandle(nullptr), kSym); |
| 135 | #else |
| 136 | void* sym= dlsym(RTLD_DEFAULT, kSym); |
| 137 | #endif |
| 138 | EXPECT_TRUE(sym!=nullptr); |
| 139 | } |
| 140 | #endif// sanitizers |
| 141 | |
glider@chromium.org | 66d051bb | 2010-10-14 08:25:54 | [diff] [blame] | 142 | // A memory leak detector should report an error in this test. |
| 143 | TEST(ToolsSanityTest,MemoryLeak){ |
thakis@chromium.org | 6bfad0e | 2011-11-01 11:08:09 | [diff] [blame] | 144 | // Without the |volatile|, clang optimizes away the next two lines. |
| 145 | int*volatile leak=newint[256];// Leak some memory intentionally. |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 146 | leak[4]=1;// Make sure the allocated memory is used. |
glider@chromium.org | 66d051bb | 2010-10-14 08:25:54 | [diff] [blame] | 147 | } |
| 148 | |
Rohit Rao | 150dc5bb | 2020-07-22 20:43:55 | [diff] [blame] | 149 | TEST(ToolsSanityTest,AccessesToNewMemory){ |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 150 | char* foo=newchar[16]; |
| 151 | MakeSomeErrors(foo,16); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 152 | delete[] foo; |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 153 | // Use after delete. |
| 154 | HARMFUL_ACCESS(foo[5]=0,"heap-use-after-free"); |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 155 | } |
| 156 | |
Rohit Rao | 150dc5bb | 2020-07-22 20:43:55 | [diff] [blame] | 157 | TEST(ToolsSanityTest,AccessesToMallocMemory){ |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 158 | char* foo=reinterpret_cast<char*>(malloc(16)); |
| 159 | MakeSomeErrors(foo,16); |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 160 | free(foo); |
glider@chromium.org | c2a1849 | 2011-10-05 13:22:50 | [diff] [blame] | 161 | // Use after free. |
| 162 | HARMFUL_ACCESS(foo[5]=0,"heap-use-after-free"); |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 163 | } |
| 164 | |
Rohit Rao | 150dc5bb | 2020-07-22 20:43:55 | [diff] [blame] | 165 | TEST(ToolsSanityTest,AccessesToStack){ |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 166 | char foo[16]; |
| 167 | |
| 168 | ReadUninitializedValue(foo); |
| 169 | HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(foo), |
David Benjamin | 533295e | 2024-07-01 22:01:14 | [diff] [blame] | 170 | "underflows this variable"); |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 171 | HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(foo,16), |
David Benjamin | 533295e | 2024-07-01 22:01:14 | [diff] [blame] | 172 | "overflows this variable"); |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 173 | HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(foo), |
David Benjamin | 533295e | 2024-07-01 22:01:14 | [diff] [blame] | 174 | "underflows this variable"); |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 175 | HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(foo,16), |
David Benjamin | 533295e | 2024-07-01 22:01:14 | [diff] [blame] | 176 | "overflows this variable"); |
Peter Collingbourne | 5a35305d | 2019-02-06 02:51:43 | [diff] [blame] | 177 | } |
| 178 | |
Sigurdur Asgeirsson | 69d0bcd | 2018-03-29 21:50:51 | [diff] [blame] | 179 | #if defined(ADDRESS_SANITIZER) |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 180 | |
Nico Weber | d1fc45e | 2022-05-03 15:45:17 | [diff] [blame] | 181 | // alloc_dealloc_mismatch defaults to |
| 182 | // !SANITIZER_MAC && !SANITIZER_WINDOWS && !SANITIZER_ANDROID, |
| 183 | // in the sanitizer runtime upstream. |
Chong Gu | 3ab0b469 | 2022-05-05 17:20:03 | [diff] [blame] | 184 | #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \ |
| 185 | BUILDFLAG(IS_FUCHSIA) |
Nico Weber | d1fc45e | 2022-05-03 15:45:17 | [diff] [blame] | 186 | #define MAYBE_SingleElementDeletedWithBraces \ |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 187 | DISABLED_SingleElementDeletedWithBraces |
Nico Weber | d1fc45e | 2022-05-03 15:45:17 | [diff] [blame] | 188 | #define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces |
| 189 | #else |
| 190 | #define MAYBE_ArrayDeletedWithoutBracesArrayDeletedWithoutBraces |
| 191 | #define MAYBE_SingleElementDeletedWithBracesSingleElementDeletedWithBraces |
| 192 | #endif// defined(ADDRESS_SANITIZER) |
| 193 | |
hans | cd4cce3 | 2015-05-19 17:03:14 | [diff] [blame] | 194 | staticint* allocateArray(){ |
| 195 | // Clang warns about the mismatched new[]/delete if they occur in the same |
| 196 | // function. |
| 197 | returnnewint[10]; |
| 198 | } |
| 199 | |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 200 | // This test may corrupt memory if not compiled with AddressSanitizer. |
glider@chromium.org | 9a4f618 | 2012-10-24 14:11:02 | [diff] [blame] | 201 | TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces){ |
thakis@chromium.org | 014b0b06 | 2011-09-18 16:30:12 | [diff] [blame] | 202 | // Without the |volatile|, clang optimizes away the next two lines. |
hans | cd4cce3 | 2015-05-19 17:03:14 | [diff] [blame] | 203 | int*volatile foo= allocateArray(); |
Nico Weber | d1fc45e | 2022-05-03 15:45:17 | [diff] [blame] | 204 | HARMFUL_ACCESS(delete foo,"alloc-dealloc-mismatch"); |
| 205 | // Under ASan the crash happens in the process spawned by HARMFUL_ACCESS, |
| 206 | // need to free the memory in the parent. |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 207 | delete[] foo; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 208 | } |
| 209 | |
hans | cd4cce3 | 2015-05-19 17:03:14 | [diff] [blame] | 210 | staticint* allocateScalar(){ |
| 211 | // Clang warns about the mismatched new/delete[] if they occur in the same |
| 212 | // function. |
| 213 | returnnewint; |
| 214 | } |
| 215 | |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 216 | // This test may corrupt memory if not compiled with AddressSanitizer. |
glider@chromium.org | 9a4f618 | 2012-10-24 14:11:02 | [diff] [blame] | 217 | TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces){ |
thakis@chromium.org | 014b0b06 | 2011-09-18 16:30:12 | [diff] [blame] | 218 | // Without the |volatile|, clang optimizes away the next two lines. |
hans | cd4cce3 | 2015-05-19 17:03:14 | [diff] [blame] | 219 | int*volatile foo= allocateScalar(); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 220 | (void)foo; |
| 221 | HARMFUL_ACCESS(delete[] foo,"alloc-dealloc-mismatch"); |
Nico Weber | d1fc45e | 2022-05-03 15:45:17 | [diff] [blame] | 222 | // Under ASan the crash happens in the process spawned by HARMFUL_ACCESS, |
| 223 | // need to free the memory in the parent. |
| 224 | delete foo; |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 225 | } |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 226 | #endif |
timurrrr@chromium.org | 9ded991 | 2010-03-26 12:54:44 | [diff] [blame] | 227 | |
glider@chromium.org | 9b147ae | 2011-11-08 09:28:49 | [diff] [blame] | 228 | TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest){ |
glider@chromium.org | 6fcbc62f | 2011-10-12 17:18:24 | [diff] [blame] | 229 | // Intentionally crash to make sure AddressSanitizer is running. |
| 230 | // This test should not be ran on bots. |
Peter Kasting | 811504a7 | 2025-01-09 03:18:50 | [diff] [blame] | 231 | int*volatile zero=nullptr; |
glider@chromium.org | 6fcbc62f | 2011-10-12 17:18:24 | [diff] [blame] | 232 | *zero=0; |
| 233 | } |
glider@chromium.org | 9b147ae | 2011-11-08 09:28:49 | [diff] [blame] | 234 | |
| 235 | TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest){ |
| 236 | // Intentionally crash to make sure AddressSanitizer is instrumenting |
| 237 | // the local variables. |
Peter Kasting | 2bc85c99 | 2025-01-13 14:19:52 | [diff] [blame] | 238 | // This test should not be run on bots. |
| 239 | int array[5];// Must not use std::array, lest hardening catch this first. |
glider@chromium.org | 9b147ae | 2011-11-08 09:28:49 | [diff] [blame] | 240 | // Work around the OOB warning reported by Clang. |
| 241 | int*volatile access=&array[5]; |
| 242 | *access=43; |
| 243 | } |
| 244 | |
| 245 | namespace{ |
| 246 | int g_asan_test_global_array[10]; |
| 247 | }// namespace |
| 248 | |
| 249 | TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest){ |
| 250 | // Intentionally crash to make sure AddressSanitizer is instrumenting |
| 251 | // the global variables. |
| 252 | // This test should not be ran on bots. |
| 253 | |
| 254 | // Work around the OOB warning reported by Clang. |
| 255 | int*volatile access= g_asan_test_global_array-1; |
| 256 | *access=43; |
| 257 | } |
| 258 | |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 259 | #ifndef HARMFUL_ACCESS_IS_NOOP |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 260 | TEST(ToolsSanityTest,AsanHeapOverflow){ |
Hans Wennborg | 2a3b7f2 | 2022-09-10 19:35:42 | [diff] [blame] | 261 | HARMFUL_ACCESS(debug::AsanHeapOverflow(),"after"); |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | TEST(ToolsSanityTest,AsanHeapUnderflow){ |
Hans Wennborg | 2a3b7f2 | 2022-09-10 19:35:42 | [diff] [blame] | 265 | HARMFUL_ACCESS(debug::AsanHeapUnderflow(),"before"); |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | TEST(ToolsSanityTest,AsanHeapUseAfterFree){ |
| 269 | HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(),"heap-use-after-free"); |
| 270 | } |
| 271 | |
Xiaohan Wang | 38e4ebb | 2022-01-19 06:57:43 | [diff] [blame] | 272 | #if BUILDFLAG(IS_WIN) |
Sigurdur Asgeirsson | 597be54 | 2018-04-04 15:44:04 | [diff] [blame] | 273 | // The ASAN runtime doesn't detect heap corruption, this needs fixing before |
| 274 | // ASAN builds can ship to the wild. See https://crbug.com/818747. |
| 275 | TEST(ToolsSanityTest, DISABLED_AsanCorruptHeapBlock){ |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 276 | HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(),""); |
| 277 | } |
| 278 | |
Sigurdur Asgeirsson | 597be54 | 2018-04-04 15:44:04 | [diff] [blame] | 279 | TEST(ToolsSanityTest, DISABLED_AsanCorruptHeap){ |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 280 | // This test will kill the process by raising an exception, there's no |
| 281 | // particular string to look for in the stack trace. |
| 282 | EXPECT_DEATH(debug::AsanCorruptHeap(),""); |
| 283 | } |
Xiaohan Wang | 38e4ebb | 2022-01-19 06:57:43 | [diff] [blame] | 284 | #endif// BUILDFLAG(IS_WIN) |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 285 | #endif// !HARMFUL_ACCESS_IS_NOOP |
sebmarchand@chromium.org | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 286 | |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 287 | namespace{ |
| 288 | |
| 289 | // We use caps here just to ensure that the method name doesn't interfere with |
| 290 | // the wildcarded suppressions. |
| 291 | class TOOLS_SANITY_TEST_CONCURRENT_THREAD:publicPlatformThread::Delegate{ |
| 292 | public: |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 293 | explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool* value): value_(value){} |
Chris Watkins | bb7211c | 2017-11-29 07:16:38 | [diff] [blame] | 294 | ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() override=default; |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 295 | voidThreadMain() override{ |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 296 | *value_=true; |
| 297 | |
| 298 | // Sleep for a few milliseconds so the two threads are more likely to live |
| 299 | // simultaneously. Otherwise we may miss the report due to mutex |
| 300 | // lock/unlock's inside thread creation code in pure-happens-before mode... |
Peter Kasting | 53fd6ee | 2021-10-05 20:40:48 | [diff] [blame] | 301 | PlatformThread::Sleep(Milliseconds(100)); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 302 | } |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 303 | |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 304 | private: |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 305 | raw_ptr<bool> value_; |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 306 | }; |
| 307 | |
| 308 | classReleaseStoreThread:publicPlatformThread::Delegate{ |
| 309 | public: |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 310 | explicitReleaseStoreThread(std::atomic<uint32_t>*value): value_(value){} |
Chris Watkins | bb7211c | 2017-11-29 07:16:38 | [diff] [blame] | 311 | ~ReleaseStoreThread() override=default; |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 312 | voidThreadMain() override{ |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 313 | value_->store(kMagicValue, std::memory_order_release); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 314 | |
| 315 | // Sleep for a few milliseconds so the two threads are more likely to live |
| 316 | // simultaneously. Otherwise we may miss the report due to mutex |
| 317 | // lock/unlock's inside thread creation code in pure-happens-before mode... |
Peter Kasting | 53fd6ee | 2021-10-05 20:40:48 | [diff] [blame] | 318 | PlatformThread::Sleep(Milliseconds(100)); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 319 | } |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 320 | |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 321 | private: |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 322 | raw_ptr<std::atomic<uint32_t>> value_; |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 323 | }; |
| 324 | |
| 325 | classAcquireLoadThread:publicPlatformThread::Delegate{ |
| 326 | public: |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 327 | explicitAcquireLoadThread(std::atomic<uint32_t>*value): value_(value){} |
Chris Watkins | bb7211c | 2017-11-29 07:16:38 | [diff] [blame] | 328 | ~AcquireLoadThread() override=default; |
dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 329 | voidThreadMain() override{ |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 330 | // Wait for the other thread to make Release_Store |
Peter Kasting | 53fd6ee | 2021-10-05 20:40:48 | [diff] [blame] | 331 | PlatformThread::Sleep(Milliseconds(100)); |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 332 | value_->load(std::memory_order_acquire); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 333 | } |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 334 | |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 335 | private: |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 336 | raw_ptr<std::atomic<uint32_t>> value_; |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 337 | }; |
| 338 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 339 | voidRunInParallel(PlatformThread::Delegate* d1,PlatformThread::Delegate* d2){ |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 340 | PlatformThreadHandle a; |
| 341 | PlatformThreadHandle b; |
| 342 | PlatformThread::Create(0, d1,&a); |
| 343 | PlatformThread::Create(0, d2,&b); |
| 344 | PlatformThread::Join(a); |
| 345 | PlatformThread::Join(b); |
| 346 | } |
| 347 | |
glider@chromium.org | b11d38d0 | 2014-06-26 13:10:50 | [diff] [blame] | 348 | #if defined(THREAD_SANITIZER) |
| 349 | voidDataRace(){ |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 350 | bool* shared=newbool(false); |
glider@chromium.org | a405798 | 2013-03-23 11:28:17 | [diff] [blame] | 351 | TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 352 | RunInParallel(&thread1,&thread2); |
glider@chromium.org | a405798 | 2013-03-23 11:28:17 | [diff] [blame] | 353 | EXPECT_TRUE(*shared); |
| 354 | delete shared; |
glider@chromium.org | b11d38d0 | 2014-06-26 13:10:50 | [diff] [blame] | 355 | // We're in a death test - crash. |
Peter Boström | 54d7f8d | 2024-11-27 23:03:11 | [diff] [blame] | 356 | NOTREACHED(); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 357 | } |
glider@chromium.org | b11d38d0 | 2014-06-26 13:10:50 | [diff] [blame] | 358 | #endif |
| 359 | |
| 360 | }// namespace |
| 361 | |
| 362 | #if defined(THREAD_SANITIZER) |
| 363 | // A data race detector should report an error in this test. |
Fumitoshi Ukai | ce2f308 | 2025-05-26 02:30:45 | [diff] [blame] | 364 | TEST(ToolsSanityTest,DataRace){ |
glider@chromium.org | b11d38d0 | 2014-06-26 13:10:50 | [diff] [blame] | 365 | // The suppression regexp must match that in base/debug/tsan_suppressions.cc. |
| 366 | EXPECT_DEATH(DataRace(),"1 race:base/tools_sanity_unittest.cc"); |
| 367 | } |
| 368 | #endif |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 369 | |
| 370 | TEST(ToolsSanityTest,AnnotateBenignRace){ |
| 371 | bool shared=false; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 372 | ABSL_ANNOTATE_BENIGN_RACE(&shared, |
| 373 | "Intentional race - make sure doesn't show up"); |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 374 | TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared); |
| 375 | RunInParallel(&thread1,&thread2); |
| 376 | EXPECT_TRUE(shared); |
| 377 | } |
| 378 | |
| 379 | TEST(ToolsSanityTest,AtomicsAreIgnored){ |
Venkatesh Srinivas | 4539c296 | 2025-05-28 23:58:57 | [diff] [blame] | 380 | std::atomic<uint32_t> shared=0; |
timurrrr@chromium.org | f49ecd8f | 2011-05-10 18:03:34 | [diff] [blame] | 381 | ReleaseStoreThread thread1(&shared); |
| 382 | AcquireLoadThread thread2(&shared); |
| 383 | RunInParallel(&thread1,&thread2); |
| 384 | EXPECT_EQ(kMagicValue, shared); |
glider@chromium.org | 0716cba | 2009-12-17 12:37:58 | [diff] [blame] | 385 | } |
brettw@chromium.org | ce072a7 | 2010-12-31 20:02:16 | [diff] [blame] | 386 | |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 387 | #if BUILDFLAG(CFI_ENFORCEMENT_TRAP) |
Xiaohan Wang | 38e4ebb | 2022-01-19 06:57:43 | [diff] [blame] | 388 | #if BUILDFLAG(IS_WIN) |
Peter Collingbourne | 355546f | 2017-10-12 19:51:27 | [diff] [blame] | 389 | #define CFI_ERROR_MSG"EXCEPTION_ILLEGAL_INSTRUCTION" |
Xiaohan Wang | 38e4ebb | 2022-01-19 06:57:43 | [diff] [blame] | 390 | #elif BUILDFLAG(IS_ANDROID) |
Peter Collingbourne | 355546f | 2017-10-12 19:51:27 | [diff] [blame] | 391 | // TODO(pcc): Produce proper stack dumps on Android and test for the correct |
| 392 | // si_code here. |
| 393 | #define CFI_ERROR_MSG"^$" |
| 394 | #else |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 395 | #define CFI_ERROR_MSG"ILL_ILLOPN" |
Peter Collingbourne | 355546f | 2017-10-12 19:51:27 | [diff] [blame] | 396 | #endif |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 397 | #elif BUILDFLAG(CFI_ENFORCEMENT_DIAGNOSTIC) |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 398 | #define CFI_ERROR_MSG"runtime error: control flow integrity check" |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 399 | #endif// BUILDFLAG(CFI_ENFORCEMENT_TRAP || CFI_ENFORCEMENT_DIAGNOSTIC) |
pcc | 0736491 | 2015-07-31 00:19:06 | [diff] [blame] | 400 | |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 401 | #if defined(CFI_ERROR_MSG) |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 402 | class A{ |
| 403 | public: |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 404 | A(): n_(0){} |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 405 | virtualvoid f(){ n_++;} |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 406 | |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 407 | protected: |
| 408 | int n_; |
| 409 | }; |
| 410 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 411 | class B:public A{ |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 412 | public: |
| 413 | void f() override{ n_--;} |
| 414 | }; |
| 415 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 416 | class C:public B{ |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 417 | public: |
| 418 | void f() override{ n_+=2;} |
| 419 | }; |
| 420 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 421 | NOINLINEvoidKillVptrAndCall(A* obj){ |
| 422 | *reinterpret_cast<void**>(obj)=0; |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 423 | obj->f(); |
| 424 | } |
| 425 | |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 426 | TEST(ToolsSanityTest,BadVirtualCallNull){ |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 427 | A a; |
| 428 | B b; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 429 | EXPECT_DEATH( |
| 430 | { |
| 431 | KillVptrAndCall(&a); |
| 432 | KillVptrAndCall(&b); |
| 433 | }, |
| 434 | CFI_ERROR_MSG); |
krasin | 59d3718 | 2016-07-13 03:24:34 | [diff] [blame] | 435 | } |
| 436 | |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 437 | NOINLINEvoidOverwriteVptrAndCall(B* obj, A* vptr){ |
| 438 | *reinterpret_cast<void**>(obj)=*reinterpret_cast<void**>(vptr); |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 439 | obj->f(); |
| 440 | } |
| 441 | |
| 442 | TEST(ToolsSanityTest,BadVirtualCallWrongType){ |
| 443 | A a; |
| 444 | B b; |
| 445 | C c; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 446 | EXPECT_DEATH( |
| 447 | { |
| 448 | OverwriteVptrAndCall(&b,&a); |
| 449 | OverwriteVptrAndCall(&b,&c); |
| 450 | }, |
| 451 | CFI_ERROR_MSG); |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 452 | } |
| 453 | |
| 454 | // TODO(pcc): remove CFI_CAST_CHECK, see https://crbug.com/626794. |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 455 | #if BUILDFLAG(CFI_CAST_CHECK) |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 456 | TEST(ToolsSanityTest,BadDerivedCast){ |
| 457 | A a; |
| 458 | EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG); |
| 459 | } |
| 460 | |
| 461 | TEST(ToolsSanityTest,BadUnrelatedCast){ |
| 462 | class A{ |
| 463 | virtualvoid f(){} |
| 464 | }; |
| 465 | |
| 466 | class B{ |
| 467 | virtualvoid f(){} |
| 468 | }; |
| 469 | |
| 470 | A a; |
| 471 | EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG); |
| 472 | } |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 473 | #endif// BUILDFLAG(CFI_CAST_CHECK) |
Vlad Tsyrklevich | 37f1e35 | 2017-08-15 23:45:10 | [diff] [blame] | 474 | |
Vlad Tsyrklevich | e0408ff | 2017-10-13 19:35:24 | [diff] [blame] | 475 | #endif// CFI_ERROR_MSG |
pcc | 0736491 | 2015-07-31 00:19:06 | [diff] [blame] | 476 | |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 477 | #undef CFI_ERROR_MSG |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 478 | #undef HARMFUL_ACCESS |
| 479 | #undef HARMFUL_ACCESS_IS_NOOP |
| 480 | |
brettw@chromium.org | ce072a7 | 2010-12-31 20:02:16 | [diff] [blame] | 481 | }// namespace base |