diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp index 752ba9ab32c71..670901e8504da 100644 --- a/compiler-rt/lib/asan/asan_allocator.cpp +++ b/compiler-rt/lib/asan/asan_allocator.cpp @@ -781,11 +781,17 @@ struct Allocator { u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire); if (chunk_state != CHUNK_ALLOCATED) ReportInvalidFree(old_ptr, chunk_state, stack); - CHECK_NE(REAL(memcpy), nullptr); uptr memcpy_size = Min(new_size, m->UsedSize()); // If realloc() races with free(), we may start copying freed memory. // However, we will report racy double-free later anyway. +#if !SANITIZER_AIX + CHECK_NE(REAL(memcpy), nullptr); REAL(memcpy)(new_ptr, old_ptr, memcpy_size); +#else + // AIX currently can't retrieve memcpy's address, we have to use + // internal_memcpy here. + internal_memcpy(new_ptr, old_ptr, memcpy_size); +#endif Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC); } return new_ptr; diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp index 8643271e89d70..8c67cef8f032d 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -56,8 +56,18 @@ namespace __asan { # define ASAN_READ_STRING(ctx, s, n) \ ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n)) -static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { -#if SANITIZER_INTERCEPT_STRNLEN +static inline void internal_or_real_memcpy(void* new_mem, const char* s, + uptr length) { +# if SANITIZER_INTERCEPT_MEMCPY + REAL(memcpy)(new_mem, s, length + 1); +# else + internal_memcpy(new_mem, s, length + 1); +# endif +} + +[[maybe_unused]] static inline uptr MaybeRealStrnlen(const char* s, + uptr maxlen) { +# if SANITIZER_INTERCEPT_STRNLEN if (static_cast(REAL(strnlen))) return REAL(strnlen)(s, maxlen); # endif @@ -282,7 +292,12 @@ INTERCEPTOR(int, pthread_create, void *thread, void *attr, # endif asanThreadArgRetval().Create(detached, {start_routine, arg}, [&]() -> uptr { result = REAL(pthread_create)(thread, attr, asan_thread_start, t); +// AIX pthread_t is unsigned int. +# if SANITIZER_AIX + return result ? 0 : *(unsigned*)(thread); +# else return result ? 0 : *(uptr *)(thread); +# endif }); } if (result != 0) { @@ -439,12 +454,14 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, #define siglongjmp __siglongjmp14 #endif +# if ASAN_INTERCEPT_LONGJMP INTERCEPTOR(void, longjmp, void *env, int val) { __asan_handle_no_return(); REAL(longjmp)(env, val); } +# endif -#if ASAN_INTERCEPT__LONGJMP +# if ASAN_INTERCEPT__LONGJMP INTERCEPTOR(void, _longjmp, void *env, int val) { __asan_handle_no_return(); REAL(_longjmp)(env, val); @@ -515,6 +532,7 @@ DEFINE_REAL(char*, index, const char *string, int c) // For both strcat() and strncat() we need to check the validity of |to| // argument irrespective of the |from| length. +# if ASAN_INTERCEPT_STRCAT INTERCEPTOR(char *, strcat, char *to, const char *from) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcat); @@ -554,7 +572,9 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, usize size) { } return REAL(strncat)(to, from, size); } +# endif +# if ASAN_INTERCEPT_STRCPY INTERCEPTOR(char *, strcpy, char *to, const char *from) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcpy); @@ -576,6 +596,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) { } return REAL(strcpy)(to, from); } +# endif INTERCEPTOR(wchar_t*, wcscpy, wchar_t* to, const wchar_t* from) { void* ctx; @@ -617,7 +638,7 @@ INTERCEPTOR(char*, strdup, const char *s) { GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); if (new_mem) { - REAL(memcpy)(new_mem, s, length + 1); + internal_or_real_memcpy(new_mem, s, length + 1); } return reinterpret_cast(new_mem); } @@ -635,12 +656,13 @@ INTERCEPTOR(char*, __strdup, const char *s) { GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); if (new_mem) { - REAL(memcpy)(new_mem, s, length + 1); + internal_or_real_memcpy(new_mem, s, length + 1); } return reinterpret_cast(new_mem); } #endif // ASAN_INTERCEPT___STRDUP +# if ASAN_INTERCEPT_STRCPY INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncpy); @@ -653,6 +675,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) { } return REAL(strncpy)(to, from, size); } +# endif INTERCEPTOR(wchar_t*, wcsncpy, wchar_t* to, const wchar_t* from, uptr size) { void* ctx; @@ -778,7 +801,15 @@ static void AtCxaAtexit(void *unused) { } #endif -#if ASAN_INTERCEPT___CXA_ATEXIT +# if ASAN_INTERCEPT_EXIT +INTERCEPTOR(void, exit, int status) { + AsanInitFromRtl(); + StopInitOrderChecking(); + REAL(exit)(status); +} +# endif + +# if ASAN_INTERCEPT___CXA_ATEXIT INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { if (SANITIZER_APPLE && UNLIKELY(!AsanInited())) @@ -839,10 +870,14 @@ void InitializeAsanInterceptors() { InitializeSignalInterceptors(); // Intercept str* functions. +# if ASAN_INTERCEPT_STRCAT ASAN_INTERCEPT_FUNC(strcat); - ASAN_INTERCEPT_FUNC(strcpy); ASAN_INTERCEPT_FUNC(strncat); +# endif +# if ASAN_INTERCEPT_STRCPY + ASAN_INTERCEPT_FUNC(strcpy); ASAN_INTERCEPT_FUNC(strncpy); +# endif ASAN_INTERCEPT_FUNC(strdup); // Intercept wcs* functions. @@ -867,7 +902,9 @@ void InitializeAsanInterceptors() { # endif // Intercept jump-related functions. +# if ASAN_INTERCEPT_LONGJMP ASAN_INTERCEPT_FUNC(longjmp); +# endif # if ASAN_INTERCEPT_SWAPCONTEXT ASAN_INTERCEPT_FUNC(swapcontext); @@ -934,7 +971,11 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(atexit); #endif -#if ASAN_INTERCEPT_PTHREAD_ATFORK +# if ASAN_INTERCEPT_EXIT + ASAN_INTERCEPT_FUNC(exit); +# endif + +# if ASAN_INTERCEPT_PTHREAD_ATFORK ASAN_INTERCEPT_FUNC(pthread_atfork); #endif diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 7081e8bbb2af0..5a3f2039c8199 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -31,10 +31,22 @@ void InitializePlatformInterceptors(); // really defined to replace libc functions. #if !SANITIZER_FUCHSIA +// AIX currently can't retrieve the address of longjmp +# if !SANITIZER_AIX +# define ASAN_INTERCEPT_LONGJMP 1 +# else +# define ASAN_INTERCEPT_LONGJMP 0 +# endif + // Use macro to describe if specific function should be // intercepted on a given platform. # if !SANITIZER_WINDOWS -# define ASAN_INTERCEPT__LONGJMP 1 + // AIX currently can't retrieve the address of _longjmp +# if !SANITIZER_AIX +# define ASAN_INTERCEPT__LONGJMP 1 +# else +# define ASAN_INTERCEPT__LONGJMP 0 +# endif # define ASAN_INTERCEPT_INDEX 1 # define ASAN_INTERCEPT_PTHREAD_CREATE 1 # else @@ -56,7 +68,8 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT_SWAPCONTEXT 0 # endif -# if !SANITIZER_WINDOWS +// AIX currently can't retrieve the address of siglongjmp +# if !SANITIZER_WINDOWS && !SANITIZER_AIX # define ASAN_INTERCEPT_SIGLONGJMP 1 # else # define ASAN_INTERCEPT_SIGLONGJMP 0 @@ -84,12 +97,19 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0 # endif -# if !SANITIZER_WINDOWS +// AIX currently can't retrieve the address of __cxa_atexit +# if !SANITIZER_WINDOWS && !SANITIZER_AIX # define ASAN_INTERCEPT___CXA_ATEXIT 1 # else # define ASAN_INTERCEPT___CXA_ATEXIT 0 # endif +# if SANITIZER_AIX +# define ASAN_INTERCEPT_EXIT 1 +# else +# define ASAN_INTERCEPT_EXIT 0 +# endif + # if SANITIZER_NETBSD # define ASAN_INTERCEPT_ATEXIT 1 # else @@ -110,6 +130,15 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT_TRYJOIN 0 # endif +// AIX currently can't retrieve the address of strcat or strcpy +# if SANITIZER_AIX +# define ASAN_INTERCEPT_STRCAT 0 +# define ASAN_INTERCEPT_STRCPY 0 +# else +# define ASAN_INTERCEPT_STRCAT 1 +# define ASAN_INTERCEPT_STRCPY 1 +# endif + # if SANITIZER_LINUX && \ (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \ defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) diff --git a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp index f52ae9ae8d17c..9e4e6e0a7696b 100644 --- a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp +++ b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp @@ -22,6 +22,16 @@ using namespace __asan; +// AIX currently can't retrieve memcpy's address, we have to use internal_memcpy +// here. +#if !SANITIZER_AIX +# define ASAN_MEMCPY_RETURN(to, from, size) REAL(memcpy)(to, from, size) +# define ASAN_MEMMOVE_RETURN(to, from, size) REAL(memmove)(to, from, size) +#else +# define ASAN_MEMCPY_RETURN(to, from, size) internal_memcpy(to, from, size) +# define ASAN_MEMMOVE_RETURN(to, from, size) internal_memmove(to, from, size) +#endif + // memcpy is called during __asan_init() from the internals of printf(...). // We do not treat memcpy with to==from as a bug. // See http://llvm.org/bugs/show_bug.cgi?id=11763. @@ -36,7 +46,7 @@ using namespace __asan; } else if (UNLIKELY(!AsanInited())) { \ return internal_memcpy(to, from, size); \ } \ - return REAL(memcpy)(to, from, size); \ + return ASAN_MEMCPY_RETURN(to, from, size); \ } while (0) // memset is called inside Printf. @@ -50,15 +60,15 @@ using namespace __asan; return REAL(memset)(block, c, size); \ } while (0) -#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ - do { \ - if (LIKELY(replace_intrin_cached)) { \ - ASAN_READ_RANGE(ctx, from, size); \ - ASAN_WRITE_RANGE(ctx, to, size); \ - } else if (UNLIKELY(!AsanInited())) { \ - return internal_memmove(to, from, size); \ - } \ - return REAL(memmove)(to, from, size); \ +#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ + do { \ + if (LIKELY(replace_intrin_cached)) { \ + ASAN_READ_RANGE(ctx, from, size); \ + ASAN_WRITE_RANGE(ctx, to, size); \ + } else if (UNLIKELY(!AsanInited())) { \ + return internal_memmove(to, from, size); \ + } \ + return ASAN_MEMMOVE_RETURN(to, from, size); \ } while (0) void *__asan_memcpy(void *to, const void *from, uptr size) { diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp index add57318785be..9250911cb8f72 100644 --- a/compiler-rt/lib/asan/asan_malloc_linux.cpp +++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp @@ -15,7 +15,7 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \ - SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU + SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_AIX # include "asan_allocator.h" # include "asan_interceptors.h" @@ -61,6 +61,24 @@ INTERCEPTOR(void, cfree, void *ptr) { } #endif // SANITIZER_INTERCEPT_CFREE +# if SANITIZER_AIX +INTERCEPTOR(void*, vec_malloc, uptr size) { + if (DlsymAlloc::Use()) + return DlsymAlloc::Allocate(size); + AsanInitFromRtl(); + GET_STACK_TRACE_MALLOC; + return asan_malloc(size, &stack); +} + +INTERCEPTOR(void*, vec_calloc, uptr nmemb, uptr size) { + if (DlsymAlloc::Use()) + return DlsymAlloc::Callocate(nmemb, size); + AsanInitFromRtl(); + GET_STACK_TRACE_MALLOC; + return asan_calloc(nmemb, size, &stack); +} +# endif + INTERCEPTOR(void*, malloc, uptr size) { if (DlsymAlloc::Use()) return DlsymAlloc::Allocate(size);