tools_sanity_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. //
  5. // This file contains intentional memory errors, some of which may lead to
  6. // crashes if the test is ran without special memory testing tools. We use these
  7. // errors to verify the sanity of the tools.
  8. #include <stddef.h>
  9. #include "base/atomicops.h"
  10. #include "base/cfi_buildflags.h"
  11. #include "base/debug/asan_invalid_access.h"
  12. #include "base/debug/profiler.h"
  13. #include "base/logging.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/sanitizer_buildflags.h"
  16. #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
  17. #include "base/threading/thread.h"
  18. #include "build/build_config.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. #if BUILDFLAG(IS_WIN)
  21. #include <windows.h>
  22. #else
  23. #include <dlfcn.h>
  24. #endif
  25. namespace base {
  26. namespace {
  27. const base::subtle::Atomic32 kMagicValue = 42;
  28. // Helper for memory accesses that can potentially corrupt memory or cause a
  29. // crash during a native run.
  30. #if defined(ADDRESS_SANITIZER)
  31. #define HARMFUL_ACCESS(action, error_regexp) \
  32. EXPECT_DEATH_IF_SUPPORTED(action, error_regexp)
  33. #elif BUILDFLAG(IS_HWASAN)
  34. #define HARMFUL_ACCESS(action, error_regexp) \
  35. EXPECT_DEATH(action, "tag-mismatch")
  36. #else
  37. #define HARMFUL_ACCESS(action, error_regexp)
  38. #define HARMFUL_ACCESS_IS_NOOP
  39. #endif
  40. void DoReadUninitializedValue(char *ptr) {
  41. // Comparison with 64 is to prevent clang from optimizing away the
  42. // jump -- valgrind only catches jumps and conditional moves, but clang uses
  43. // the borrow flag if the condition is just `*ptr == '\0'`. We no longer
  44. // support valgrind, but this constant should be fine to keep as-is.
  45. if (*ptr == 64) {
  46. VLOG(1) << "Uninit condition is true";
  47. } else {
  48. VLOG(1) << "Uninit condition is false";
  49. }
  50. }
  51. void ReadUninitializedValue(char *ptr) {
  52. #if defined(MEMORY_SANITIZER)
  53. EXPECT_DEATH(DoReadUninitializedValue(ptr),
  54. "use-of-uninitialized-value");
  55. #else
  56. DoReadUninitializedValue(ptr);
  57. #endif
  58. }
  59. #ifndef HARMFUL_ACCESS_IS_NOOP
  60. void ReadValueOutOfArrayBoundsLeft(char *ptr) {
  61. char c = ptr[-2];
  62. VLOG(1) << "Reading a byte out of bounds: " << c;
  63. }
  64. void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
  65. char c = ptr[size + 1];
  66. VLOG(1) << "Reading a byte out of bounds: " << c;
  67. }
  68. void WriteValueOutOfArrayBoundsLeft(char *ptr) {
  69. ptr[-1] = kMagicValue;
  70. }
  71. void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
  72. ptr[size] = kMagicValue;
  73. }
  74. #endif // HARMFUL_ACCESS_IS_NOOP
  75. void MakeSomeErrors(char *ptr, size_t size) {
  76. ReadUninitializedValue(ptr);
  77. HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(ptr),
  78. "2 bytes to the left");
  79. HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(ptr, size),
  80. "1 bytes to the right");
  81. HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(ptr),
  82. "1 bytes to the left");
  83. HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(ptr, size),
  84. "0 bytes to the right");
  85. }
  86. } // namespace
  87. #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
  88. defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
  89. defined(UNDEFINED_SANITIZER)
  90. // build/sanitizers/sanitizer_options.cc defines symbols like
  91. // __asan_default_options which the sanitizer runtime calls if they exist
  92. // in the executable. If they don't, the sanitizer runtime silently uses an
  93. // internal default value instead. The build puts the symbol
  94. // _sanitizer_options_link_helper (which the sanitizer runtime doesn't know
  95. // about, it's a chrome thing) in that file and then tells the linker that
  96. // that symbol must exist. This causes sanitizer_options.cc to be part of
  97. // our binaries, which in turn makes sure our __asan_default_options are used.
  98. // We had problems with __asan_default_options not being used, so this test
  99. // verifies that _sanitizer_options_link_helper actually makes it into our
  100. // binaries.
  101. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
  102. // TODO(https://crbug.com/1322143): Sanitizer options are currently broken
  103. // on Android.
  104. // TODO(https://crbug.com/1321584): __asan_default_options should be used
  105. // on Windows too, but currently isn't.
  106. #define MAYBE_LinksSanitizerOptions DISABLED_LinksSanitizerOptions
  107. #else
  108. #define MAYBE_LinksSanitizerOptions LinksSanitizerOptions
  109. #endif
  110. TEST(ToolsSanityTest, MAYBE_LinksSanitizerOptions) {
  111. constexpr char kSym[] = "_sanitizer_options_link_helper";
  112. #if BUILDFLAG(IS_WIN)
  113. auto sym = GetProcAddress(GetModuleHandle(nullptr), kSym);
  114. #else
  115. void* sym = dlsym(RTLD_DEFAULT, kSym);
  116. #endif
  117. EXPECT_TRUE(sym != nullptr);
  118. }
  119. #endif // sanitizers
  120. // A memory leak detector should report an error in this test.
  121. TEST(ToolsSanityTest, MemoryLeak) {
  122. // Without the |volatile|, clang optimizes away the next two lines.
  123. int* volatile leak = new int[256]; // Leak some memory intentionally.
  124. leak[4] = 1; // Make sure the allocated memory is used.
  125. }
  126. TEST(ToolsSanityTest, AccessesToNewMemory) {
  127. char* foo = new char[16];
  128. MakeSomeErrors(foo, 16);
  129. delete [] foo;
  130. // Use after delete.
  131. HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
  132. }
  133. TEST(ToolsSanityTest, AccessesToMallocMemory) {
  134. char* foo = reinterpret_cast<char*>(malloc(16));
  135. MakeSomeErrors(foo, 16);
  136. free(foo);
  137. // Use after free.
  138. HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
  139. }
  140. TEST(ToolsSanityTest, AccessesToStack) {
  141. char foo[16];
  142. ReadUninitializedValue(foo);
  143. HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(foo),
  144. "underflows this variable");
  145. HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(foo, 16),
  146. "overflows this variable");
  147. HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(foo),
  148. "underflows this variable");
  149. HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(foo, 16),
  150. "overflows this variable");
  151. }
  152. #if defined(ADDRESS_SANITIZER)
  153. // alloc_dealloc_mismatch defaults to
  154. // !SANITIZER_MAC && !SANITIZER_WINDOWS && !SANITIZER_ANDROID,
  155. // in the sanitizer runtime upstream.
  156. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \
  157. BUILDFLAG(IS_FUCHSIA)
  158. #define MAYBE_SingleElementDeletedWithBraces \
  159. DISABLED_SingleElementDeletedWithBraces
  160. #define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces
  161. #else
  162. #define MAYBE_ArrayDeletedWithoutBraces ArrayDeletedWithoutBraces
  163. #define MAYBE_SingleElementDeletedWithBraces SingleElementDeletedWithBraces
  164. #endif // defined(ADDRESS_SANITIZER)
  165. static int* allocateArray() {
  166. // Clang warns about the mismatched new[]/delete if they occur in the same
  167. // function.
  168. return new int[10];
  169. }
  170. // This test may corrupt memory if not compiled with AddressSanitizer.
  171. TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) {
  172. // Without the |volatile|, clang optimizes away the next two lines.
  173. int* volatile foo = allocateArray();
  174. HARMFUL_ACCESS(delete foo, "alloc-dealloc-mismatch");
  175. // Under ASan the crash happens in the process spawned by HARMFUL_ACCESS,
  176. // need to free the memory in the parent.
  177. delete [] foo;
  178. }
  179. static int* allocateScalar() {
  180. // Clang warns about the mismatched new/delete[] if they occur in the same
  181. // function.
  182. return new int;
  183. }
  184. // This test may corrupt memory if not compiled with AddressSanitizer.
  185. TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces) {
  186. // Without the |volatile|, clang optimizes away the next two lines.
  187. int* volatile foo = allocateScalar();
  188. (void) foo;
  189. HARMFUL_ACCESS(delete [] foo, "alloc-dealloc-mismatch");
  190. // Under ASan the crash happens in the process spawned by HARMFUL_ACCESS,
  191. // need to free the memory in the parent.
  192. delete foo;
  193. }
  194. #endif
  195. TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) {
  196. // Intentionally crash to make sure AddressSanitizer is running.
  197. // This test should not be ran on bots.
  198. int* volatile zero = NULL;
  199. *zero = 0;
  200. }
  201. TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest) {
  202. // Intentionally crash to make sure AddressSanitizer is instrumenting
  203. // the local variables.
  204. // This test should not be ran on bots.
  205. int array[5];
  206. // Work around the OOB warning reported by Clang.
  207. int* volatile access = &array[5];
  208. *access = 43;
  209. }
  210. namespace {
  211. int g_asan_test_global_array[10];
  212. } // namespace
  213. TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest) {
  214. // Intentionally crash to make sure AddressSanitizer is instrumenting
  215. // the global variables.
  216. // This test should not be ran on bots.
  217. // Work around the OOB warning reported by Clang.
  218. int* volatile access = g_asan_test_global_array - 1;
  219. *access = 43;
  220. }
  221. #ifndef HARMFUL_ACCESS_IS_NOOP
  222. TEST(ToolsSanityTest, AsanHeapOverflow) {
  223. HARMFUL_ACCESS(debug::AsanHeapOverflow(), "to the right");
  224. }
  225. TEST(ToolsSanityTest, AsanHeapUnderflow) {
  226. HARMFUL_ACCESS(debug::AsanHeapUnderflow(), "to the left");
  227. }
  228. TEST(ToolsSanityTest, AsanHeapUseAfterFree) {
  229. HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(), "heap-use-after-free");
  230. }
  231. #if BUILDFLAG(IS_WIN)
  232. // The ASAN runtime doesn't detect heap corruption, this needs fixing before
  233. // ASAN builds can ship to the wild. See https://crbug.com/818747.
  234. TEST(ToolsSanityTest, DISABLED_AsanCorruptHeapBlock) {
  235. HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(), "");
  236. }
  237. TEST(ToolsSanityTest, DISABLED_AsanCorruptHeap) {
  238. // This test will kill the process by raising an exception, there's no
  239. // particular string to look for in the stack trace.
  240. EXPECT_DEATH(debug::AsanCorruptHeap(), "");
  241. }
  242. #endif // BUILDFLAG(IS_WIN)
  243. #endif // !HARMFUL_ACCESS_IS_NOOP
  244. namespace {
  245. // We use caps here just to ensure that the method name doesn't interfere with
  246. // the wildcarded suppressions.
  247. class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
  248. public:
  249. explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
  250. ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() override = default;
  251. void ThreadMain() override {
  252. *value_ = true;
  253. // Sleep for a few milliseconds so the two threads are more likely to live
  254. // simultaneously. Otherwise we may miss the report due to mutex
  255. // lock/unlock's inside thread creation code in pure-happens-before mode...
  256. PlatformThread::Sleep(Milliseconds(100));
  257. }
  258. private:
  259. raw_ptr<bool> value_;
  260. };
  261. class ReleaseStoreThread : public PlatformThread::Delegate {
  262. public:
  263. explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {}
  264. ~ReleaseStoreThread() override = default;
  265. void ThreadMain() override {
  266. base::subtle::Release_Store(value_, kMagicValue);
  267. // Sleep for a few milliseconds so the two threads are more likely to live
  268. // simultaneously. Otherwise we may miss the report due to mutex
  269. // lock/unlock's inside thread creation code in pure-happens-before mode...
  270. PlatformThread::Sleep(Milliseconds(100));
  271. }
  272. private:
  273. raw_ptr<base::subtle::Atomic32> value_;
  274. };
  275. class AcquireLoadThread : public PlatformThread::Delegate {
  276. public:
  277. explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {}
  278. ~AcquireLoadThread() override = default;
  279. void ThreadMain() override {
  280. // Wait for the other thread to make Release_Store
  281. PlatformThread::Sleep(Milliseconds(100));
  282. base::subtle::Acquire_Load(value_);
  283. }
  284. private:
  285. raw_ptr<base::subtle::Atomic32> value_;
  286. };
  287. void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) {
  288. PlatformThreadHandle a;
  289. PlatformThreadHandle b;
  290. PlatformThread::Create(0, d1, &a);
  291. PlatformThread::Create(0, d2, &b);
  292. PlatformThread::Join(a);
  293. PlatformThread::Join(b);
  294. }
  295. #if defined(THREAD_SANITIZER)
  296. void DataRace() {
  297. bool *shared = new bool(false);
  298. TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared);
  299. RunInParallel(&thread1, &thread2);
  300. EXPECT_TRUE(*shared);
  301. delete shared;
  302. // We're in a death test - crash.
  303. CHECK(0);
  304. }
  305. #endif
  306. } // namespace
  307. #if defined(THREAD_SANITIZER)
  308. // A data race detector should report an error in this test.
  309. TEST(ToolsSanityTest, DataRace) {
  310. // The suppression regexp must match that in base/debug/tsan_suppressions.cc.
  311. EXPECT_DEATH(DataRace(), "1 race:base/tools_sanity_unittest.cc");
  312. }
  313. #endif
  314. TEST(ToolsSanityTest, AnnotateBenignRace) {
  315. bool shared = false;
  316. ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up");
  317. TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
  318. RunInParallel(&thread1, &thread2);
  319. EXPECT_TRUE(shared);
  320. }
  321. TEST(ToolsSanityTest, AtomicsAreIgnored) {
  322. base::subtle::Atomic32 shared = 0;
  323. ReleaseStoreThread thread1(&shared);
  324. AcquireLoadThread thread2(&shared);
  325. RunInParallel(&thread1, &thread2);
  326. EXPECT_EQ(kMagicValue, shared);
  327. }
  328. #if BUILDFLAG(CFI_ENFORCEMENT_TRAP)
  329. #if BUILDFLAG(IS_WIN)
  330. #define CFI_ERROR_MSG "EXCEPTION_ILLEGAL_INSTRUCTION"
  331. #elif BUILDFLAG(IS_ANDROID)
  332. // TODO(pcc): Produce proper stack dumps on Android and test for the correct
  333. // si_code here.
  334. #define CFI_ERROR_MSG "^$"
  335. #else
  336. #define CFI_ERROR_MSG "ILL_ILLOPN"
  337. #endif
  338. #elif BUILDFLAG(CFI_ENFORCEMENT_DIAGNOSTIC)
  339. #define CFI_ERROR_MSG "runtime error: control flow integrity check"
  340. #endif // BUILDFLAG(CFI_ENFORCEMENT_TRAP || CFI_ENFORCEMENT_DIAGNOSTIC)
  341. #if defined(CFI_ERROR_MSG)
  342. class A {
  343. public:
  344. A(): n_(0) {}
  345. virtual void f() { n_++; }
  346. protected:
  347. int n_;
  348. };
  349. class B: public A {
  350. public:
  351. void f() override { n_--; }
  352. };
  353. class C: public B {
  354. public:
  355. void f() override { n_ += 2; }
  356. };
  357. NOINLINE void KillVptrAndCall(A *obj) {
  358. *reinterpret_cast<void **>(obj) = 0;
  359. obj->f();
  360. }
  361. TEST(ToolsSanityTest, BadVirtualCallNull) {
  362. A a;
  363. B b;
  364. EXPECT_DEATH({ KillVptrAndCall(&a); KillVptrAndCall(&b); }, CFI_ERROR_MSG);
  365. }
  366. NOINLINE void OverwriteVptrAndCall(B *obj, A *vptr) {
  367. *reinterpret_cast<void **>(obj) = *reinterpret_cast<void **>(vptr);
  368. obj->f();
  369. }
  370. TEST(ToolsSanityTest, BadVirtualCallWrongType) {
  371. A a;
  372. B b;
  373. C c;
  374. EXPECT_DEATH({ OverwriteVptrAndCall(&b, &a); OverwriteVptrAndCall(&b, &c); },
  375. CFI_ERROR_MSG);
  376. }
  377. // TODO(pcc): remove CFI_CAST_CHECK, see https://crbug.com/626794.
  378. #if BUILDFLAG(CFI_CAST_CHECK)
  379. TEST(ToolsSanityTest, BadDerivedCast) {
  380. A a;
  381. EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
  382. }
  383. TEST(ToolsSanityTest, BadUnrelatedCast) {
  384. class A {
  385. virtual void f() {}
  386. };
  387. class B {
  388. virtual void f() {}
  389. };
  390. A a;
  391. EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
  392. }
  393. #endif // BUILDFLAG(CFI_CAST_CHECK)
  394. #endif // CFI_ERROR_MSG
  395. #undef CFI_ERROR_MSG
  396. #undef HARMFUL_ACCESS
  397. #undef HARMFUL_ACCESS_IS_NOOP
  398. } // namespace base