On Thu, May 22, 2014 at 3:43 PM, Jakub Jelinek <[email protected]> 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 <[email protected]>
>
> * 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