From 365884e24d9eea08c1d3737fef87c23d26950c72 Mon Sep 17 00:00:00 2001 From: jakub Date: Fri, 30 May 2014 18:36:24 +0000 Subject: [PATCH] * g++.dg/asan/asan_test.C: Add -std=c++11 and -DSANITIZER_USE_DEJAGNU_GTEST=1 to dg-options, remove -DASAN_USE_DEJAGNU_GTEST=1. * g++.dg/asan/asan_mem_test.cc: Updated from upstream r209283. * g++.dg/asan/asan_oob_test.cc: Likewise. * g++.dg/asan/sanitizer_test_utils.h: Likewise. * g++.dg/asan/asan_str_test.cc: Likewise. * g++.dg/asan/asan_test_utils.h: Likewise. * g++.dg/asan/sanitizer_test_config.h: Likewise. * g++.dg/asan/asan_test.cc: Likewise. Allow size 12 for long double. * g++.dg/asan/sanitizer_pthread_wrappers.h: New file. Imported from upstream r209283. * g++.dg/asan/asan_test_config.h: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211090 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/testsuite/ChangeLog | 18 + gcc/testsuite/g++.dg/asan/asan_mem_test.cc | 22 +- gcc/testsuite/g++.dg/asan/asan_oob_test.cc | 2 - gcc/testsuite/g++.dg/asan/asan_str_test.cc | 37 ++- gcc/testsuite/g++.dg/asan/asan_test.C | 2 +- gcc/testsuite/g++.dg/asan/asan_test.cc | 370 +++++++++++++-------- gcc/testsuite/g++.dg/asan/asan_test_config.h | 16 +- gcc/testsuite/g++.dg/asan/asan_test_utils.h | 24 +- .../g++.dg/asan/sanitizer_pthread_wrappers.h | 64 ++++ gcc/testsuite/g++.dg/asan/sanitizer_test_config.h | 28 ++ gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h | 74 ++++- 11 files changed, 468 insertions(+), 189 deletions(-) create mode 100644 gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h create mode 100644 gcc/testsuite/g++.dg/asan/sanitizer_test_config.h diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7990eb4a1ea..8beaf53879c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2014-05-30 Jakub Jelinek + + * g++.dg/asan/asan_test.C: Add -std=c++11 and + -DSANITIZER_USE_DEJAGNU_GTEST=1 to dg-options, remove + -DASAN_USE_DEJAGNU_GTEST=1. + * g++.dg/asan/asan_mem_test.cc: Updated from upstream + r209283. + * g++.dg/asan/asan_oob_test.cc: Likewise. + * g++.dg/asan/sanitizer_test_utils.h: Likewise. + * g++.dg/asan/asan_str_test.cc: Likewise. + * g++.dg/asan/asan_test_utils.h: Likewise. + * g++.dg/asan/sanitizer_test_config.h: Likewise. + * g++.dg/asan/asan_test.cc: Likewise. Allow size 12 + for long double. + * g++.dg/asan/sanitizer_pthread_wrappers.h: New file. + Imported from upstream r209283. + * g++.dg/asan/asan_test_config.h: Likewise. + 2014-05-30 Ian Lance Taylor * gcc.target/i386/pause-2.c: New test. diff --git a/gcc/testsuite/g++.dg/asan/asan_mem_test.cc b/gcc/testsuite/g++.dg/asan/asan_mem_test.cc index 5656aab0bac..5fc4af7e9e3 100644 --- a/gcc/testsuite/g++.dg/asan/asan_mem_test.cc +++ b/gcc/testsuite/g++.dg/asan/asan_mem_test.cc @@ -74,17 +74,17 @@ TEST(AddressSanitizer, MemSetOOBTest) { // Strictly speaking we are not guaranteed to find such two pointers, // but given the structure of asan's allocator we will. static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) { - vector v; + vector v; bool res = false; for (size_t i = 0; i < 1000U && !res; i++) { - v.push_back(new char[size]); + v.push_back(reinterpret_cast(new char[size])); if (i == 0) continue; sort(v.begin(), v.end()); for (size_t j = 1; j < v.size(); j++) { assert(v[j] > v[j-1]); if ((size_t)(v[j] - v[j-1]) < size * 2) { - *x2 = v[j]; - *x1 = v[j-1]; + *x2 = reinterpret_cast(v[j]); + *x1 = reinterpret_cast(v[j-1]); res = true; break; } @@ -92,9 +92,10 @@ static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) { } for (size_t i = 0; i < v.size(); i++) { - if (res && v[i] == *x1) continue; - if (res && v[i] == *x2) continue; - delete [] v[i]; + char *p = reinterpret_cast(v[i]); + if (res && p == *x1) continue; + if (res && p == *x2) continue; + delete [] p; } return res; } @@ -223,6 +224,13 @@ TEST(AddressSanitizer, MemCmpOOBTest) { s1[size - 1] = '\0'; s2[size - 1] = '\0'; EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); + + // Even if the buffers differ in the first byte, we still assume that + // memcmp may access the whole buffer and thus reporting the overflow here: + s1[0] = 1; + s2[0] = 123; + EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); + free(s1); free(s2); } diff --git a/gcc/testsuite/g++.dg/asan/asan_oob_test.cc b/gcc/testsuite/g++.dg/asan/asan_oob_test.cc index 61d50553703..2361dc286d7 100644 --- a/gcc/testsuite/g++.dg/asan/asan_oob_test.cc +++ b/gcc/testsuite/g++.dg/asan/asan_oob_test.cc @@ -97,7 +97,6 @@ TEST(AddressSanitizer, OOBRightTest) { } } -#if ASAN_ALLOCATOR_VERSION == 2 // Broken with the asan_allocator1 TEST(AddressSanitizer, LargeOOBRightTest) { size_t large_power_of_two = 1 << 19; for (size_t i = 16; i <= 256; i *= 2) { @@ -107,7 +106,6 @@ TEST(AddressSanitizer, LargeOOBRightTest) { delete [] p; } } -#endif // ASAN_ALLOCATOR_VERSION == 2 TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) { oob_test(10, -1); diff --git a/gcc/testsuite/g++.dg/asan/asan_str_test.cc b/gcc/testsuite/g++.dg/asan/asan_str_test.cc index 1b9805e8eb1..207de422316 100644 --- a/gcc/testsuite/g++.dg/asan/asan_str_test.cc +++ b/gcc/testsuite/g++.dg/asan/asan_str_test.cc @@ -10,6 +10,10 @@ //===----------------------------------------------------------------------===// #include "asan_test_utils.h" +#if defined(__APPLE__) +#include // For MAC_OS_X_VERSION_* +#endif + // Used for string functions tests static char global_string[] = "global"; static size_t global_string_length = 6; @@ -59,7 +63,19 @@ TEST(AddressSanitizer, StrLenOOBTest) { free(heap_string); } -#ifndef __APPLE__ +TEST(AddressSanitizer, WcsLenTest) { + EXPECT_EQ(0U, wcslen(Ident(L""))); + size_t hello_len = 13; + size_t hello_size = (hello_len + 1) * sizeof(wchar_t); + EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!"))); + wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size)); + memcpy(heap_string, L"Hello, World!", hello_size); + EXPECT_EQ(hello_len, Ident(wcslen(heap_string))); + EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0)); + free(heap_string); +} + +#if SANITIZER_TEST_HAS_STRNLEN TEST(AddressSanitizer, StrNLenOOBTest) { size_t size = Ident(123); char *str = MallocAndMemsetString(size); @@ -77,7 +93,7 @@ TEST(AddressSanitizer, StrNLenOOBTest) { EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0)); free(str); } -#endif +#endif // SANITIZER_TEST_HAS_STRNLEN TEST(AddressSanitizer, StrDupOOBTest) { size_t size = Ident(42); @@ -168,7 +184,7 @@ TEST(AddressSanitizer, StrNCpyOOBTest) { typedef char*(*PointerToStrChr1)(const char*, int); typedef char*(*PointerToStrChr2)(char*, int); -USED static void RunStrChrTest(PointerToStrChr1 StrChr) { +UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr) { size_t size = Ident(100); char *str = MallocAndMemsetString(size); str[10] = 'q'; @@ -184,7 +200,7 @@ USED static void RunStrChrTest(PointerToStrChr1 StrChr) { EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0)); free(str); } -USED static void RunStrChrTest(PointerToStrChr2 StrChr) { +UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr) { size_t size = Ident(100); char *str = MallocAndMemsetString(size); str[10] = 'q'; @@ -203,7 +219,9 @@ USED static void RunStrChrTest(PointerToStrChr2 StrChr) { TEST(AddressSanitizer, StrChrAndIndexOOBTest) { RunStrChrTest(&strchr); +#if !defined(_WIN32) // no index() on Windows. RunStrChrTest(&index); +#endif } TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { @@ -226,6 +244,7 @@ TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { EXPECT_LT(0, strncmp("baa", "aaa", 1)); EXPECT_LT(0, strncmp("zyx", "", 2)); +#if !defined(_WIN32) // no str[n]casecmp on Windows. // strcasecmp EXPECT_EQ(0, strcasecmp("", "")); EXPECT_EQ(0, strcasecmp("zzz", "zzz")); @@ -245,6 +264,7 @@ TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { EXPECT_LT(0, strncasecmp("xyz", "xyy", 10)); EXPECT_LT(0, strncasecmp("Baa", "aaa", 1)); EXPECT_LT(0, strncasecmp("zyx", "", 2)); +#endif // memcmp EXPECT_EQ(0, memcmp("a", "b", 0)); @@ -287,9 +307,11 @@ TEST(AddressSanitizer, StrCmpOOBTest) { RunStrCmpTest(&strcmp); } +#if !defined(_WIN32) // no str[n]casecmp on Windows. TEST(AddressSanitizer, StrCaseCmpOOBTest) { RunStrCmpTest(&strcasecmp); } +#endif typedef int(*PointerToStrNCmp)(const char*, const char*, size_t); void RunStrNCmpTest(PointerToStrNCmp StrNCmp) { @@ -322,9 +344,12 @@ TEST(AddressSanitizer, StrNCmpOOBTest) { RunStrNCmpTest(&strncmp); } +#if !defined(_WIN32) // no str[n]casecmp on Windows. TEST(AddressSanitizer, StrNCaseCmpOOBTest) { RunStrNCmpTest(&strncasecmp); } +#endif + TEST(AddressSanitizer, StrCatOOBTest) { // strcat() reads strlen(to) bytes from |to| before concatenating. size_t to_size = Ident(100); @@ -506,11 +531,13 @@ void RunAtoiOOBTest(PointerToCallAtoi Atoi) { free(array); } +#if !defined(_WIN32) // FIXME: Fix and enable on Windows. TEST(AddressSanitizer, AtoiAndFriendsOOBTest) { RunAtoiOOBTest(&CallAtoi); RunAtoiOOBTest(&CallAtol); RunAtoiOOBTest(&CallAtoll); } +#endif void CallStrtol(const char *nptr, char **endptr, int base) { Ident(strtol(nptr, endptr, base)); @@ -560,11 +587,13 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) { free(array); } +#if !defined(_WIN32) // FIXME: Fix and enable on Windows. TEST(AddressSanitizer, StrtollOOBTest) { RunStrtolOOBTest(&CallStrtoll); } TEST(AddressSanitizer, StrtolOOBTest) { RunStrtolOOBTest(&CallStrtol); } +#endif diff --git a/gcc/testsuite/g++.dg/asan/asan_test.C b/gcc/testsuite/g++.dg/asan/asan_test.C index e11531e07de..3cee7150f73 100644 --- a/gcc/testsuite/g++.dg/asan/asan_test.C +++ b/gcc/testsuite/g++.dg/asan/asan_test.C @@ -2,7 +2,7 @@ // { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } // { dg-skip-if "" { *-*-* } { "-flto" } { "" } } // { dg-additional-sources "asan_globals_test-wrapper.cc" } -// { dg-options "-fsanitize=address -fno-builtin -Wall -Wno-format -Werror -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DASAN_USE_DEJAGNU_GTEST=1 -lasan -lpthread -ldl" } +// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Wno-format -Werror -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread -ldl" } // { dg-additional-options "-DASAN_NEEDS_SEGV=1" { target { ! arm*-*-* } } } // { dg-additional-options "-DASAN_LOW_MEMORY=1 -DASAN_NEEDS_SEGV=0" { target arm*-*-* } } // { dg-additional-options "-DASAN_AVOID_EXPENSIVE_TESTS=1" { target { ! run_expensive_tests } } } diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc index 2df8c62cbb1..5f2e2c244dd 100644 --- a/gcc/testsuite/g++.dg/asan/asan_test.cc +++ b/gcc/testsuite/g++.dg/asan/asan_test.cc @@ -23,27 +23,10 @@ NOINLINE void *malloc_bbb(size_t size) { NOINLINE void *malloc_aaa(size_t size) { void *res = malloc_bbb(size); break_optimization(0); return res;} -#ifndef __APPLE__ -NOINLINE void *memalign_fff(size_t alignment, size_t size) { - void *res = memalign/**/(alignment, size); break_optimization(0); return res;} -NOINLINE void *memalign_eee(size_t alignment, size_t size) { - void *res = memalign_fff(alignment, size); break_optimization(0); return res;} -NOINLINE void *memalign_ddd(size_t alignment, size_t size) { - void *res = memalign_eee(alignment, size); break_optimization(0); return res;} -NOINLINE void *memalign_ccc(size_t alignment, size_t size) { - void *res = memalign_ddd(alignment, size); break_optimization(0); return res;} -NOINLINE void *memalign_bbb(size_t alignment, size_t size) { - void *res = memalign_ccc(alignment, size); break_optimization(0); return res;} -NOINLINE void *memalign_aaa(size_t alignment, size_t size) { - void *res = memalign_bbb(alignment, size); break_optimization(0); return res;} -#endif // __APPLE__ - - NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);} NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);} NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);} - template NOINLINE void uaf_test(int size, int off) { char *p = (char *)malloc_aaa(size); @@ -88,19 +71,19 @@ TEST(AddressSanitizer, VariousMallocsTest) { *c = 0; delete c; -#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__) +#if SANITIZER_TEST_HAS_POSIX_MEMALIGN int *pm; int pm_res = posix_memalign((void**)&pm, kPageSize, kPageSize); EXPECT_EQ(0, pm_res); free(pm); -#endif +#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN -#if !defined(__APPLE__) +#if SANITIZER_TEST_HAS_MEMALIGN int *ma = (int*)memalign(kPageSize, kPageSize); EXPECT_EQ(0U, (uintptr_t)ma % kPageSize); ma[123] = 0; free(ma); -#endif // __APPLE__ +#endif // SANITIZER_TEST_HAS_MEMALIGN } TEST(AddressSanitizer, CallocTest) { @@ -109,13 +92,37 @@ TEST(AddressSanitizer, CallocTest) { free(a); } +TEST(AddressSanitizer, CallocReturnsZeroMem) { + size_t sizes[] = {16, 1000, 10000, 100000, 2100000}; + for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) { + size_t size = sizes[s]; + for (size_t iter = 0; iter < 5; iter++) { + char *x = Ident((char*)calloc(1, size)); + EXPECT_EQ(x[0], 0); + EXPECT_EQ(x[size - 1], 0); + EXPECT_EQ(x[size / 2], 0); + EXPECT_EQ(x[size / 3], 0); + EXPECT_EQ(x[size / 4], 0); + memset(x, 0x42, size); + free(Ident(x)); +#if !defined(_WIN32) + // FIXME: OOM on Windows. We should just make this a lit test + // with quarantine size set to 1. + free(Ident(malloc(Ident(1 << 27)))); // Try to drain the quarantine. +#endif + } + } +} + +#if !defined(_WIN32) // No valloc on Windows. TEST(AddressSanitizer, VallocTest) { void *a = valloc(100); EXPECT_EQ(0U, (uintptr_t)a % kPageSize); free(a); } +#endif -#ifndef __APPLE__ +#if SANITIZER_TEST_HAS_PVALLOC TEST(AddressSanitizer, PvallocTest) { char *a = (char*)pvalloc(kPageSize + 100); EXPECT_EQ(0U, (uintptr_t)a % kPageSize); @@ -127,8 +134,10 @@ TEST(AddressSanitizer, PvallocTest) { a[101] = 1; // we should not report an error here. free(a); } -#endif // __APPLE__ +#endif // SANITIZER_TEST_HAS_PVALLOC +#if !defined(_WIN32) +// FIXME: Use an equivalent of pthread_setspecific on Windows. void *TSDWorker(void *test_key) { if (test_key) { pthread_setspecific(*(pthread_key_t*)test_key, (void*)0xfeedface); @@ -158,6 +167,7 @@ TEST(AddressSanitizer, DISABLED_TSDTest) { PTHREAD_JOIN(th, NULL); pthread_key_delete(test_key); } +#endif TEST(AddressSanitizer, UAF_char) { const char *uaf_string = "AddressSanitizer:.*heap-use-after-free"; @@ -168,6 +178,36 @@ TEST(AddressSanitizer, UAF_char) { EXPECT_DEATH(uaf_test(kLargeMalloc, kLargeMalloc / 2), uaf_string); } +TEST(AddressSanitizer, UAF_long_double) { + if (sizeof(long double) == sizeof(double)) return; + long double *p = Ident(new long double[10]); + EXPECT_DEATH(Ident(p)[12] = 0, "WRITE of size 1[026]"); + EXPECT_DEATH(Ident(p)[0] = Ident(p)[12], "READ of size 1[026]"); + delete [] Ident(p); +} + +#if !defined(_WIN32) +struct Packed5 { + int x; + char c; +} __attribute__((packed)); +#else +# pragma pack(push, 1) +struct Packed5 { + int x; + char c; +}; +# pragma pack(pop) +#endif + +TEST(AddressSanitizer, UAF_Packed5) { + static_assert(sizeof(Packed5) == 5, "Please check the keywords used"); + Packed5 *p = Ident(new Packed5[2]); + EXPECT_DEATH(p[0] = p[3], "READ of size 5"); + EXPECT_DEATH(p[3] = p[0], "WRITE of size 5"); + delete [] Ident(p); +} + #if ASAN_HAS_BLACKLIST TEST(AddressSanitizer, IgnoreTest) { int *x = Ident(new int); @@ -244,41 +284,6 @@ TEST(AddressSanitizer, SignalTest) { } // namespace #endif -static void MallocStress(size_t n) { - uint32_t seed = my_rand(); - for (size_t iter = 0; iter < 10; iter++) { - vector vec; - for (size_t i = 0; i < n; i++) { - if ((i % 3) == 0) { - if (vec.empty()) continue; - size_t idx = my_rand_r(&seed) % vec.size(); - void *ptr = vec[idx]; - vec[idx] = vec.back(); - vec.pop_back(); - free_aaa(ptr); - } else { - size_t size = my_rand_r(&seed) % 1000 + 1; -#ifndef __APPLE__ - size_t alignment = 1 << (my_rand_r(&seed) % 7 + 3); - char *ptr = (char*)memalign_aaa(alignment, size); -#else - char *ptr = (char*) malloc_aaa(size); -#endif - vec.push_back(ptr); - ptr[0] = 0; - ptr[size-1] = 0; - ptr[size/2] = 0; - } - } - for (size_t i = 0; i < vec.size(); i++) - free_aaa(vec[i]); - } -} - -TEST(AddressSanitizer, MallocStressTest) { - MallocStress((ASAN_LOW_MEMORY) ? 20000 : 200000); -} - static void TestLargeMalloc(size_t size) { char buff[1024]; sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size); @@ -286,28 +291,21 @@ static void TestLargeMalloc(size_t size) { } TEST(AddressSanitizer, LargeMallocTest) { - for (int i = 113; i < (1 << 28); i = i * 2 + 13) { + const int max_size = (SANITIZER_WORDSIZE == 32) ? 1 << 26 : 1 << 28; + for (int i = 113; i < max_size; i = i * 2 + 13) { TestLargeMalloc(i); } } -#if ASAN_LOW_MEMORY != 1 TEST(AddressSanitizer, HugeMallocTest) { -#ifdef __APPLE__ - // It was empirically found out that 1215 megabytes is the maximum amount of - // memory available to the process under AddressSanitizer on 32-bit Mac 10.6. - // 32-bit Mac 10.7 gives even less (< 1G). - // (the libSystem malloc() allows allocating up to 2300 megabytes without - // ASan). - size_t n_megs = SANITIZER_WORDSIZE == 32 ? 500 : 4100; -#else - size_t n_megs = SANITIZER_WORDSIZE == 32 ? 2600 : 4100; -#endif - TestLargeMalloc(n_megs << 20); + if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return; + size_t n_megs = 4100; + EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0, + "is located 1 bytes to the left|" + "AddressSanitizer failed to allocate"); } -#endif -#ifndef __APPLE__ +#if SANITIZER_TEST_HAS_MEMALIGN void MemalignRun(size_t align, size_t size, int idx) { char *p = (char *)memalign(align, size); Ident(p)[idx] = 0; @@ -323,20 +321,7 @@ TEST(AddressSanitizer, memalign) { "is located 1 bytes to the right"); } } -#endif - -TEST(AddressSanitizer, ThreadedMallocStressTest) { - const int kNumThreads = 4; - const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress, - (void*)kNumIterations); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} +#endif // SANITIZER_TEST_HAS_MEMALIGN void *ManyThreadsWorker(void *a) { for (int iter = 0; iter < 100; iter++) { @@ -377,17 +362,30 @@ TEST(AddressSanitizer, ReallocTest) { free(ptr2); } +TEST(AddressSanitizer, ReallocFreedPointerTest) { + void *ptr = Ident(malloc(42)); + ASSERT_TRUE(NULL != ptr); + free(ptr); + EXPECT_DEATH(ptr = realloc(ptr, 77), "attempting double-free"); +} + +TEST(AddressSanitizer, ReallocInvalidPointerTest) { + void *ptr = Ident(malloc(42)); + EXPECT_DEATH(ptr = realloc((int*)ptr + 1, 77), "attempting free.*not malloc"); + free(ptr); +} + TEST(AddressSanitizer, ZeroSizeMallocTest) { // Test that malloc(0) and similar functions don't return NULL. void *ptr = Ident(malloc(0)); EXPECT_TRUE(NULL != ptr); free(ptr); -#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__) +#if SANITIZER_TEST_HAS_POSIX_MEMALIGN int pm_res = posix_memalign(&ptr, 1<<20, 0); EXPECT_EQ(0, pm_res); EXPECT_TRUE(NULL != ptr); free(ptr); -#endif +#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN int *int_ptr = new int[0]; int *int_ptr2 = new int[0]; EXPECT_TRUE(NULL != int_ptr); @@ -397,7 +395,7 @@ TEST(AddressSanitizer, ZeroSizeMallocTest) { delete[] int_ptr2; } -#ifndef __APPLE__ +#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE static const char *kMallocUsableSizeErrorMsg = "AddressSanitizer: attempting to call malloc_usable_size()"; @@ -413,8 +411,9 @@ TEST(AddressSanitizer, MallocUsableSizeTest) { kMallocUsableSizeErrorMsg); free(array); EXPECT_DEATH(malloc_usable_size(array), kMallocUsableSizeErrorMsg); + delete int_ptr; } -#endif +#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE void WrongFree() { int *x = (int*)malloc(100 * sizeof(int)); @@ -423,10 +422,14 @@ void WrongFree() { free(x + 1); } +#if !defined(_WIN32) // FIXME: This should be a lit test. TEST(AddressSanitizer, WrongFreeTest) { - EXPECT_DEATH(WrongFree(), - "ERROR: AddressSanitizer: attempting free.*not malloc"); + EXPECT_DEATH(WrongFree(), ASAN_PCRE_DOTALL + "ERROR: AddressSanitizer: attempting free.*not malloc" + ".*is located 4 bytes inside of 400-byte region" + ".*allocated by thread"); } +#endif void DoubleFree() { int *x = (int*)malloc(100 * sizeof(int)); @@ -437,6 +440,7 @@ void DoubleFree() { abort(); } +#if !defined(_WIN32) // FIXME: This should be a lit test. TEST(AddressSanitizer, DoubleFreeTest) { EXPECT_DEATH(DoubleFree(), ASAN_PCRE_DOTALL "ERROR: AddressSanitizer: attempting double-free" @@ -444,20 +448,22 @@ TEST(AddressSanitizer, DoubleFreeTest) { ".*freed by thread T0 here" ".*previously allocated by thread T0 here"); } +#endif template NOINLINE void SizedStackTest() { char a[kSize]; char *A = Ident((char*)&a); + const char *expected_death = "AddressSanitizer: stack-buffer-"; for (size_t i = 0; i < kSize; i++) A[i] = i; - EXPECT_DEATH(A[-1] = 0, ""); - EXPECT_DEATH(A[-20] = 0, ""); - EXPECT_DEATH(A[-31] = 0, ""); - EXPECT_DEATH(A[kSize] = 0, ""); - EXPECT_DEATH(A[kSize + 1] = 0, ""); - EXPECT_DEATH(A[kSize + 10] = 0, ""); - EXPECT_DEATH(A[kSize + 31] = 0, ""); + EXPECT_DEATH(A[-1] = 0, expected_death); + EXPECT_DEATH(A[-5] = 0, expected_death); + EXPECT_DEATH(A[kSize] = 0, expected_death); + EXPECT_DEATH(A[kSize + 1] = 0, expected_death); + EXPECT_DEATH(A[kSize + 5] = 0, expected_death); + if (kSize > 16) + EXPECT_DEATH(A[kSize + 31] = 0, expected_death); } TEST(AddressSanitizer, SimpleStackTest) { @@ -478,6 +484,9 @@ TEST(AddressSanitizer, SimpleStackTest) { SizedStackTest<128>(); } +#if !defined(_WIN32) +// FIXME: It's a bit hard to write multi-line death test expectations +// in a portable way. Anyways, this should just be turned into a lit test. TEST(AddressSanitizer, ManyStackObjectsTest) { char XXX[10]; char YYY[20]; @@ -486,6 +495,47 @@ TEST(AddressSanitizer, ManyStackObjectsTest) { Ident(YYY); EXPECT_DEATH(Ident(ZZZ)[-1] = 0, ASAN_PCRE_DOTALL "XXX.*YYY.*ZZZ"); } +#endif + +#if 0 // This test requires online symbolizer. +// Moved to lit_tests/stack-oob-frames.cc. +// Reenable here once we have online symbolizer by default. +NOINLINE static void Frame0(int frame, char *a, char *b, char *c) { + char d[4] = {0}; + char *D = Ident(d); + switch (frame) { + case 3: a[5]++; break; + case 2: b[5]++; break; + case 1: c[5]++; break; + case 0: D[5]++; break; + } +} +NOINLINE static void Frame1(int frame, char *a, char *b) { + char c[4] = {0}; Frame0(frame, a, b, c); + break_optimization(0); +} +NOINLINE static void Frame2(int frame, char *a) { + char b[4] = {0}; Frame1(frame, a, b); + break_optimization(0); +} +NOINLINE static void Frame3(int frame) { + char a[4] = {0}; Frame2(frame, a); + break_optimization(0); +} + +TEST(AddressSanitizer, GuiltyStackFrame0Test) { + EXPECT_DEATH(Frame3(0), "located .*in frame <.*Frame0"); +} +TEST(AddressSanitizer, GuiltyStackFrame1Test) { + EXPECT_DEATH(Frame3(1), "located .*in frame <.*Frame1"); +} +TEST(AddressSanitizer, GuiltyStackFrame2Test) { + EXPECT_DEATH(Frame3(2), "located .*in frame <.*Frame2"); +} +TEST(AddressSanitizer, GuiltyStackFrame3Test) { + EXPECT_DEATH(Frame3(3), "located .*in frame <.*Frame3"); +} +#endif NOINLINE void LongJmpFunc1(jmp_buf buf) { // create three red zones for these two stack objects. @@ -498,6 +548,24 @@ NOINLINE void LongJmpFunc1(jmp_buf buf) { longjmp(buf, 1); } +NOINLINE void TouchStackFunc() { + int a[100]; // long array will intersect with redzones from LongJmpFunc1. + int *A = Ident(a); + for (int i = 0; i < 100; i++) + A[i] = i*i; +} + +// Test that we handle longjmp and do not report false positives on stack. +TEST(AddressSanitizer, LongJmpTest) { + static jmp_buf buf; + if (!setjmp(buf)) { + LongJmpFunc1(buf); + } else { + TouchStackFunc(); + } +} + +#if !defined(_WIN32) // Only basic longjmp is available on Windows. NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { // create three red zones for these two stack objects. int a; @@ -531,25 +599,10 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { siglongjmp(buf, 1); } - -NOINLINE void TouchStackFunc() { - int a[100]; // long array will intersect with redzones from LongJmpFunc1. - int *A = Ident(a); - for (int i = 0; i < 100; i++) - A[i] = i*i; -} - -// Test that we handle longjmp and do not report fals positives on stack. -TEST(AddressSanitizer, LongJmpTest) { - static jmp_buf buf; - if (!setjmp(buf)) { - LongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} - -#if not defined(__ANDROID__) +#if !defined(__ANDROID__) && \ + !defined(__powerpc64__) && !defined(__powerpc__) +// Does not work on Power: +// https://code.google.com/p/address-sanitizer/issues/detail?id=185 TEST(AddressSanitizer, BuiltinLongJmpTest) { static jmp_buf buf; if (!__builtin_setjmp((void**)buf)) { @@ -558,7 +611,8 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) { TouchStackFunc(); } } -#endif // not defined(__ANDROID__) +#endif // !defined(__ANDROID__) && !defined(__powerpc64__) && + // !defined(__powerpc__) TEST(AddressSanitizer, UnderscopeLongJmpTest) { static jmp_buf buf; @@ -577,8 +631,10 @@ TEST(AddressSanitizer, SigLongJmpTest) { TouchStackFunc(); } } +#endif -#ifdef __EXCEPTIONS +// FIXME: Why does clang-cl define __EXCEPTIONS? +#if defined(__EXCEPTIONS) && !defined(_WIN32) NOINLINE void ThrowFunc() { // create three red zones for these two stack objects. int a; @@ -626,7 +682,8 @@ TEST(AddressSanitizer, ThreadStackReuseTest) { PTHREAD_JOIN(t, 0); } -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i686__) || defined(__x86_64__) +#include TEST(AddressSanitizer, Store128Test) { char *a = Ident((char*)malloc(Ident(12))); char *p = a; @@ -644,11 +701,19 @@ TEST(AddressSanitizer, Store128Test) { } #endif +// FIXME: All tests that use this function should be turned into lit tests. string RightOOBErrorMessage(int oob_distance, bool is_write) { assert(oob_distance >= 0); char expected_str[100]; - sprintf(expected_str, ASAN_PCRE_DOTALL "%s.*located %d bytes to the right", - is_write ? "WRITE" : "READ", oob_distance); + sprintf(expected_str, ASAN_PCRE_DOTALL +#if !GTEST_USES_SIMPLE_RE + "buffer-overflow.*%s.*" +#endif + "located %d bytes to the right", +#if !GTEST_USES_SIMPLE_RE + is_write ? "WRITE" : "READ", +#endif + oob_distance); return string(expected_str); } @@ -660,11 +725,19 @@ string RightOOBReadMessage(int oob_distance) { return RightOOBErrorMessage(oob_distance, /*is_write*/false); } +// FIXME: All tests that use this function should be turned into lit tests. string LeftOOBErrorMessage(int oob_distance, bool is_write) { assert(oob_distance > 0); char expected_str[100]; - sprintf(expected_str, ASAN_PCRE_DOTALL "%s.*located %d bytes to the left", - is_write ? "WRITE" : "READ", oob_distance); + sprintf(expected_str, +#if !GTEST_USES_SIMPLE_RE + ASAN_PCRE_DOTALL "%s.*" +#endif + "located %d bytes to the left", +#if !GTEST_USES_SIMPLE_RE + is_write ? "WRITE" : "READ", +#endif + oob_distance); return string(expected_str); } @@ -818,6 +891,7 @@ void ThreadedTestSpawn() { PTHREAD_JOIN(t, 0); } +#if !defined(_WIN32) // FIXME: This should be a lit test. TEST(AddressSanitizer, ThreadedTest) { EXPECT_DEATH(ThreadedTestSpawn(), ASAN_PCRE_DOTALL @@ -825,6 +899,7 @@ TEST(AddressSanitizer, ThreadedTest) { ".*Thread T.*created" ".*Thread T.*created"); } +#endif void *ThreadedTestFunc(void *unused) { // Check if prctl(PR_SET_NAME) is supported. Return if not. @@ -855,7 +930,11 @@ TEST(AddressSanitizer, ShadowGapTest) { #if SANITIZER_WORDSIZE == 32 char *addr = (char*)0x22000000; #else +# if defined(__powerpc64__) + char *addr = (char*)0x024000800000; +# else char *addr = (char*)0x0000100000080000; +# endif #endif EXPECT_DEATH(*addr = 1, "AddressSanitizer: SEGV on unknown"); } @@ -1015,7 +1094,8 @@ TEST(AddressSanitizer, PthreadExitTest) { } } -#ifdef __EXCEPTIONS +// FIXME: Why does clang-cl define __EXCEPTIONS? +#if defined(__EXCEPTIONS) && !defined(_WIN32) NOINLINE static void StackReuseAndException() { int large_stack[1000]; Ident(large_stack); @@ -1033,12 +1113,14 @@ TEST(AddressSanitizer, DISABLED_StressStackReuseAndExceptionsTest) { } #endif +#if !defined(_WIN32) TEST(AddressSanitizer, MlockTest) { EXPECT_EQ(0, mlockall(MCL_CURRENT)); EXPECT_EQ(0, mlock((void*)0x12345, 0x5678)); EXPECT_EQ(0, munlockall()); EXPECT_EQ(0, munlock((void*)0x987, 0x654)); } +#endif struct LargeStruct { int foo[100]; @@ -1051,19 +1133,26 @@ TEST(AddressSanitizer, LargeStructCopyTest) { *Ident(&a) = *Ident(&a); } -ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS -static void NoAddressSafety() { +ATTRIBUTE_NO_SANITIZE_ADDRESS +static void NoSanitizeAddress() { char *foo = new char[10]; Ident(foo)[10] = 0; delete [] foo; } -TEST(AddressSanitizer, AttributeNoAddressSafetyTest) { - Ident(NoAddressSafety)(); +TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) { + Ident(NoSanitizeAddress)(); } -// It doesn't work on Android, as calls to new/delete go through malloc/free. -#if !defined(ANDROID) && !defined(__ANDROID__) +// The new/delete/etc mismatch checks don't work on Android, +// as calls to new/delete go through malloc/free. +// OS X support is tracked here: +// https://code.google.com/p/address-sanitizer/issues/detail?id=131 +// Windows support is tracked here: +// https://code.google.com/p/address-sanitizer/issues/detail?id=309 +#if !defined(ANDROID) && !defined(__ANDROID__) && \ + !defined(__APPLE__) && \ + !defined(_WIN32) static string MismatchStr(const string &str) { return string("AddressSanitizer: alloc-dealloc-mismatch \\(") + str; } @@ -1177,3 +1266,18 @@ TEST(AddressSanitizer, LongDoubleNegativeTest) { memcpy(Ident(&a), Ident(&b), sizeof(long double)); memcpy(Ident(&c), Ident(&b), sizeof(long double)); } + +#if !defined(_WIN32) +TEST(AddressSanitizer, pthread_getschedparam) { + int policy; + struct sched_param param; + EXPECT_DEATH( + pthread_getschedparam(pthread_self(), &policy, Ident(¶m) + 2), + "AddressSanitizer: stack-buffer-.*flow"); + EXPECT_DEATH( + pthread_getschedparam(pthread_self(), Ident(&policy) - 1, ¶m), + "AddressSanitizer: stack-buffer-.*flow"); + int res = pthread_getschedparam(pthread_self(), &policy, ¶m); + ASSERT_EQ(0, res); +} +#endif diff --git a/gcc/testsuite/g++.dg/asan/asan_test_config.h b/gcc/testsuite/g++.dg/asan/asan_test_config.h index b039dc8beb2..97b7dd0873f 100644 --- a/gcc/testsuite/g++.dg/asan/asan_test_config.h +++ b/gcc/testsuite/g++.dg/asan/asan_test_config.h @@ -19,12 +19,6 @@ #include #include -#if ASAN_USE_DEJAGNU_GTEST -# include "dejagnu-gtest.h" -#else -# include "gtest/gtest.h" -#endif - using std::string; using std::vector; using std::map; @@ -42,11 +36,11 @@ using std::map; #endif #ifndef ASAN_NEEDS_SEGV -# error "please define ASAN_NEEDS_SEGV" -#endif - -#ifndef ASAN_LOW_MEMORY -# define ASAN_LOW_MEMORY 0 +# if defined(_WIN32) +# define ASAN_NEEDS_SEGV 0 +# else +# define ASAN_NEEDS_SEGV 1 +# endif #endif #ifndef ASAN_AVOID_EXPENSIVE_TESTS diff --git a/gcc/testsuite/g++.dg/asan/asan_test_utils.h b/gcc/testsuite/g++.dg/asan/asan_test_utils.h index 5ea7d4449f4..f5281a6a9e3 100644 --- a/gcc/testsuite/g++.dg/asan/asan_test_utils.h +++ b/gcc/testsuite/g++.dg/asan/asan_test_utils.h @@ -12,24 +12,28 @@ #ifndef ASAN_TEST_UTILS_H #define ASAN_TEST_UTILS_H -#if !defined(ASAN_EXTERNAL_TEST_CONFIG) +#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG) # define INCLUDED_FROM_ASAN_TEST_UTILS_H # include "asan_test_config.h" # undef INCLUDED_FROM_ASAN_TEST_UTILS_H #endif #include "sanitizer_test_utils.h" +#include "sanitizer_pthread_wrappers.h" + #include #include #include #include -#include -#include #include -#include #include #include -#include + +#if !defined(_WIN32) +# include +# include +# include +#endif #ifdef __linux__ # include @@ -39,18 +43,10 @@ #include #endif -#if defined(__i386__) || defined(__x86_64__) -#include -#endif - -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__FreeBSD__) #include #endif -// Check that pthread_create/pthread_join return success. -#define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d)) -#define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b)) - #if ASAN_HAS_EXCEPTIONS # define ASAN_THROW(x) throw (x) #else diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h b/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h new file mode 100644 index 00000000000..2e71ecbb333 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h @@ -0,0 +1,64 @@ +//===-- sanitizer_pthread_wrappers.h ----------------------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of *Sanitizer runtime. +// It provides handy wrappers for thread manipulation, that: +// a) assert on any failure rather than returning an error code +// b) defines pthread-like interface on platforms where where +// is not supplied by default. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_PTHREAD_WRAPPERS_H +#define SANITIZER_PTHREAD_WRAPPERS_H + +#include "sanitizer_test_utils.h" + +#if !defined(_WIN32) +# include +// Simply forward the arguments and check that the pthread functions succeed. +# define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d)) +# define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b)) +#else +typedef HANDLE pthread_t; + +struct PthreadHelperCreateThreadInfo { + void *(*start_routine)(void *); + void *arg; +}; + +inline DWORD WINAPI PthreadHelperThreadProc(void *arg) { + PthreadHelperCreateThreadInfo *start_data = + reinterpret_cast(arg); + void *ret = (start_data->start_routine)(start_data->arg); + delete start_data; + return (DWORD)ret; +} + +inline void PTHREAD_CREATE(pthread_t *thread, void *attr, + void *(*start_routine)(void *), void *arg) { + ASSERT_EQ(0, attr) << "Thread attributes are not supported yet."; + PthreadHelperCreateThreadInfo *data = new PthreadHelperCreateThreadInfo; + data->start_routine = start_routine; + data->arg = arg; + *thread = CreateThread(0, 0, PthreadHelperThreadProc, data, 0, 0); + ASSERT_NE(nullptr, *thread) << "Failed to create a thread."; +} + +inline void PTHREAD_JOIN(pthread_t thread, void **value_ptr) { + ASSERT_EQ(0, value_ptr) << "Nonzero value_ptr is not supported yet."; + ASSERT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE)); + ASSERT_NE(0, CloseHandle(thread)); +} + +inline void pthread_exit(void *retval) { + ASSERT_EQ(0, retval) << "Nonzero retval is not supported yet."; + ExitThread((DWORD)retval); +} +#endif // _WIN32 + +#endif // SANITIZER_PTHREAD_WRAPPERS_H diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h b/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h new file mode 100644 index 00000000000..a819a4097a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h @@ -0,0 +1,28 @@ +//===-- sanitizer_test_config.h ---------------------------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of *Sanitizer runtime. +// +//===----------------------------------------------------------------------===// +#if !defined(INCLUDED_FROM_SANITIZER_TEST_UTILS_H) +# error "This file should be included into sanitizer_test_utils.h only" +#endif + +#ifndef SANITIZER_TEST_CONFIG_H +#define SANITIZER_TEST_CONFIG_H + +#include +#include +#include + +#if SANITIZER_USE_DEJAGNU_GTEST +# include "dejagnu-gtest.h" +#else +# include "gtest/gtest.h" +#endif + +#endif // SANITIZER_TEST_CONFIG_H diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h b/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h index 99720c354fa..b118de1d346 100644 --- a/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h +++ b/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h @@ -14,32 +14,47 @@ #define SANITIZER_TEST_UTILS_H #if defined(_WIN32) -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; +// should always be the first include on Windows. +# include +// MSVS headers define max/min as macros, so std::max/min gets crazy. +# undef max +# undef min +#endif + +#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG) +# define INCLUDED_FROM_SANITIZER_TEST_UTILS_H +# include "sanitizer_test_config.h" +# undef INCLUDED_FROM_SANITIZER_TEST_UTILS_H +#endif + +#include + +#if defined(_MSC_VER) # define NOINLINE __declspec(noinline) -# define USED -#else // defined(_WIN32) +#else // defined(_MSC_VER) # define NOINLINE __attribute__((noinline)) +#endif // defined(_MSC_VER) + +#if !defined(_MSC_VER) || defined(__clang__) +# define UNUSED __attribute__((unused)) # define USED __attribute__((used)) -#include -#endif // defined(_WIN32) +#else +# define UNUSED +# define USED +#endif #if !defined(__has_feature) #define __has_feature(x) 0 #endif -#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \ +#ifndef ATTRIBUTE_NO_SANITIZE_ADDRESS +# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define ATTRIBUTE_NO_SANITIZE_ADDRESS \ __attribute__((no_sanitize_address)) -#else -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS -#endif +# else +# define ATTRIBUTE_NO_SANITIZE_ADDRESS +# endif +#endif // ATTRIBUTE_NO_SANITIZE_ADDRESS #if __LP64__ || defined(_WIN64) # define SANITIZER_WORDSIZE 64 @@ -49,7 +64,9 @@ typedef __int64 int64_t; // Make the compiler thinks that something is going on there. inline void break_optimization(void *arg) { +#if !defined(_WIN32) || defined(__clang__) __asm__ __volatile__("" : : "r" (arg) : "memory"); +#endif } // This function returns its parameter but in such a way that compiler @@ -74,5 +91,28 @@ static inline uint32_t my_rand() { return my_rand_r(&global_seed); } +// Set availability of platform-specific functions. + +#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__) && !defined(_WIN32) +# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 1 +#else +# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 0 +#endif + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32) +# define SANITIZER_TEST_HAS_MEMALIGN 1 +# define SANITIZER_TEST_HAS_PVALLOC 1 +# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 1 +#else +# define SANITIZER_TEST_HAS_MEMALIGN 0 +# define SANITIZER_TEST_HAS_PVALLOC 0 +# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 0 +#endif + +#if !defined(__APPLE__) +# define SANITIZER_TEST_HAS_STRNLEN 1 +#else +# define SANITIZER_TEST_HAS_STRNLEN 0 +#endif #endif // SANITIZER_TEST_UTILS_H -- 2.11.4.GIT