On Thu, May 22, 2014 at 3:43 PM, Jakub Jelinek <ja...@redhat.com> wrote: > On Thu, May 22, 2014 at 01:03:48PM +0200, Jakub Jelinek wrote: >> There are various other changes to asan_test.cc, so guess some work is >> needed on that. > > Ok, tried to merge also g++.dg/asan from the same revision as you've merged > libsanitizer. Oh, cool.
> > On x86_64-linux, both -m32 and -m64 I see > FAIL: g++.dg/asan/asan_test.C -O2 AddressSanitizer_UAF_Packed5 p[0] = p[3] > execution test > FAIL: g++.dg/asan/asan_test.C -O2 AddressSanitizer_UAF_Packed5 p[3] = p[0] > execution test > and with -m32 additionally: > FAIL: g++.dg/asan/asan_test.C -O2 AddressSanitizer_UAF_long_double > Ident(p)[12] = 0 execution test > FAIL: g++.dg/asan/asan_test.C -O2 AddressSanitizer_UAF_long_double > Ident(p)[0] = Ident(p)[12] execution test > The former boils down into: > struct Packed5 { > int x; > char c; > } __attribute__((packed)); > > int > main () > { > Packed5 *p = new Packed5[2]; > asm volatile ("" : "+r" (p)); > p[0] = p[3]; > p[3] = p[0]; > return 0; > } > > Right now we instrument only accesses which have sizes power of two > <= 16: > > size_in_bytes = int_size_in_bytes (type); > if ((size_in_bytes & (size_in_bytes - 1)) != 0 > || (unsigned HOST_WIDE_INT) size_in_bytes - 1 >= 16) > return; > > I thought so did LLVM, has that changed recently? Not really recently... (Feb 2013) http://llvm.org/viewvc/llvm-project?rev=175507&view=rev --kcc > > 2014-05-22 Jakub Jelinek <ja...@redhat.com> > > * 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. > * g++.dg/asan/sanitizer_pthread_wrappers.h: New file. > Imported from upstream r209283. > * g++.dg/asan/asan_test_config.h: Likewise. > > --- gcc/testsuite/g++.dg/asan/asan_test.C.jj 2013-02-14 09:38:05.000000000 > +0100 > +++ gcc/testsuite/g++.dg/asan/asan_test.C 2014-05-22 13:22:33.747459933 > +0200 > @@ -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 } } } > --- gcc/testsuite/g++.dg/asan/asan_mem_test.cc.jj 2013-02-14 > 09:38:05.697773648 +0100 > +++ gcc/testsuite/g++.dg/asan/asan_mem_test.cc 2014-05-22 13:13:48.158014955 > +0200 > @@ -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<char *> v; > + vector<uintptr_t> v; > bool res = false; > for (size_t i = 0; i < 1000U && !res; i++) { > - v.push_back(new char[size]); > + v.push_back(reinterpret_cast<uintptr_t>(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<char*>(v[j]); > + *x1 = reinterpret_cast<char*>(v[j-1]); > res = true; > break; > } > @@ -92,9 +92,10 @@ static bool AllocateTwoAdjacentArrays(ch > } > > 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<char *>(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); > } > --- gcc/testsuite/g++.dg/asan/asan_oob_test.cc.jj 2013-02-14 > 09:38:05.697773648 +0100 > +++ gcc/testsuite/g++.dg/asan/asan_oob_test.cc 2014-05-22 13:13:49.976009670 > +0200 > @@ -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<U1>(10, -1); > --- gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h.jj 2013-02-28 > 22:22:03.000000000 +0100 > +++ gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h 2014-05-22 > 13:10:27.781920740 +0200 > @@ -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; > +// <windows.h> should always be the first include on Windows. > +# include <windows.h> > +// 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 <stdint.h> > + > +#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 <stdint.h> > -#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 > --- gcc/testsuite/g++.dg/asan/asan_test_config.h.jj 2012-12-03 > 12:44:28.983724406 +0100 > +++ gcc/testsuite/g++.dg/asan/asan_test_config.h 2014-05-22 > 13:13:53.392991725 +0200 > @@ -19,12 +19,6 @@ > #include <string> > #include <map> > > -#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 > --- gcc/testsuite/g++.dg/asan/asan_str_test.cc.jj 2013-02-14 > 09:38:05.697773648 +0100 > +++ gcc/testsuite/g++.dg/asan/asan_str_test.cc 2014-05-22 13:13:51.694002758 > +0200 > @@ -10,6 +10,10 @@ > > //===----------------------------------------------------------------------===// > #include "asan_test_utils.h" > > +#if defined(__APPLE__) > +#include <AvailabilityMacros.h> // 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(PointerTo > 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(PointerTo > > TEST(AddressSanitizer, StrChrAndIndexOOBTest) { > RunStrChrTest(&strchr); > +#if !defined(_WIN32) // no index() on Windows. > RunStrChrTest(&index); > +#endif > } > > TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { > @@ -226,6 +244,7 @@ TEST(AddressSanitizer, StrCmpAndFriendsL > 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, StrCmpAndFriendsL > 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 At > 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(PointerToCallStrto > free(array); > } > > +#if !defined(_WIN32) // FIXME: Fix and enable on Windows. > TEST(AddressSanitizer, StrtollOOBTest) { > RunStrtolOOBTest(&CallStrtoll); > } > TEST(AddressSanitizer, StrtolOOBTest) { > RunStrtolOOBTest(&CallStrtol); > } > +#endif > > > --- gcc/testsuite/g++.dg/asan/asan_test_utils.h.jj 2013-02-14 > 09:38:05.688773689 +0100 > +++ gcc/testsuite/g++.dg/asan/asan_test_utils.h 2014-05-22 13:13:55.087985295 > +0200 > @@ -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 <stdio.h> > #include <signal.h> > #include <stdlib.h> > #include <string.h> > -#include <strings.h> > -#include <pthread.h> > #include <stdint.h> > -#include <setjmp.h> > #include <assert.h> > #include <algorithm> > -#include <sys/mman.h> > + > +#if !defined(_WIN32) > +# include <strings.h> > +# include <sys/mman.h> > +# include <setjmp.h> > +#endif > > #ifdef __linux__ > # include <sys/prctl.h> > @@ -39,18 +43,10 @@ > #include <unistd.h> > #endif > > -#if defined(__i386__) || defined(__x86_64__) > -#include <emmintrin.h> > -#endif > - > -#ifndef __APPLE__ > +#if !defined(__APPLE__) && !defined(__FreeBSD__) > #include <malloc.h> > #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 > --- gcc/testsuite/g++.dg/asan/asan_test.cc.jj 2013-11-12 11:31:20.000000000 > +0100 > +++ gcc/testsuite/g++.dg/asan/asan_test.cc 2014-05-22 13:08:39.223454867 > +0200 > @@ -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<typename T> > NOINLINE void uaf_test(int size, int off) { > char *p = (char *)malloc_aaa(size); > @@ -88,19 +71,19 @@ TEST(AddressSanitizer, VariousMallocsTes > *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<U1>(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[06]"); > + EXPECT_DEATH(Ident(p)[0] = Ident(p)[12], "READ of size 1[06]"); > + 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<void *> 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, ZeroSizeMallocTes > 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, MallocUsableSizeT > 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<int kSize> > 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, ManyStackObjectsT > 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 > 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, BuiltinLongJmpTes > 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, ThreadStackReuseT > PTHREAD_JOIN(t, 0); > } > > -#if defined(__i386__) || defined(__x86_64__) > +#if defined(__i686__) || defined(__x86_64__) > +#include <emmintrin.h> > 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_dista > 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_StressSt > } > #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, LargeStructCopyTe > *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, LongDoubleNegativ > 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 > --- gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h.jj 2014-05-22 > 13:20:42.496012107 +0200 > +++ gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h 2014-05-22 > 13:20:45.523996247 +0200 > @@ -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 <pthread.h> > +// is not supplied by default. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef SANITIZER_PTHREAD_WRAPPERS_H > +#define SANITIZER_PTHREAD_WRAPPERS_H > + > +#include "sanitizer_test_utils.h" > + > +#if !defined(_WIN32) > +# include <pthread.h> > +// 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<PthreadHelperCreateThreadInfo*>(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 > --- gcc/testsuite/g++.dg/asan/sanitizer_test_config.h.jj 2014-05-22 > 13:11:24.552661120 +0200 > +++ gcc/testsuite/g++.dg/asan/sanitizer_test_config.h 2014-05-22 > 13:11:28.153650267 +0200 > @@ -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 <vector> > +#include <string> > +#include <map> > + > +#if SANITIZER_USE_DEJAGNU_GTEST > +# include "dejagnu-gtest.h" > +#else > +# include "gtest/gtest.h" > +#endif > + > +#endif // SANITIZER_TEST_CONFIG_H > > > Jakub