Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1c2952c
[sanitizer_common] Implement interceptors for AIX
jakeegan Mar 18, 2025
549b134
Define SANITIZER_AIX temporarily to build
jakeegan Mar 24, 2025
d3301a3
Revert "Define SANITIZER_AIX temporarily to build"
jakeegan Mar 24, 2025
6ffa232
convert to preprocessor directives
jakeegan Mar 24, 2025
4890013
Fix formatting
jakeegan Apr 1, 2025
dcde670
Add asan interceptor part
jakeegan Apr 23, 2025
c254027
Merge branch 'main' into asan_common3
jakeegan Apr 27, 2025
878a567
Remove typo
jakeegan Apr 27, 2025
7cc64a1
Fix undeclared identifier
jakeegan Apr 27, 2025
4159aa9
Correct backslash mistake
jakeegan Apr 27, 2025
b0098db
Fix return
jakeegan Apr 27, 2025
b159f20
Fix formatting
jakeegan Apr 28, 2025
67317ad
Move misplaced endif
jakeegan Apr 28, 2025
16a2d81
Split code to different PRs
jakeegan May 5, 2025
0935ed2
Use proper naming convention
jakeegan May 5, 2025
30d1f12
Move return
jakeegan May 5, 2025
38a520d
Remove accidental change
jakeegan May 6, 2025
4c8cd38
Remove accidental change
jakeegan May 6, 2025
8ce7b54
Fix build fail
jakeegan May 6, 2025
fb70384
Address comments
jakeegan May 27, 2025
b024cac
Address comments
jakeegan May 27, 2025
b57eee8
Forgot __strdup
jakeegan May 27, 2025
c3ff763
Fix formatting
jakeegan May 27, 2025
ab72dfa
Swap to unsigned
jakeegan Jun 24, 2025
72b85c9
Update comments
jakeegan Jul 7, 2025
93a5093
Forgot siglongjmp
jakeegan Jul 7, 2025
ad0b183
Fix siglongjmp comment
jakeegan Jul 7, 2025
1b40995
Fix formatting
jakeegan Jul 7, 2025
b7d52db
Merge branch 'main' into asan_common3
jakeegan Nov 19, 2025
cab7b84
Merge branch 'main' into asan_common3
jakeegan Nov 20, 2025
18a60b9
Handle memmove too
jakeegan Dec 2, 2025
0048e02
Fix formatting
jakeegan Dec 2, 2025
54f6a42
Merge branch 'main' into asan_common3
jakeegan Dec 10, 2025
cb545f5
Fix formatting
jakeegan Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion compiler-rt/lib/asan/asan_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,16 @@ 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 does not intercept memcpy, 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;
Expand Down
57 changes: 49 additions & 8 deletions compiler-rt/lib/asan/asan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the logical reason to use SANITIZER_INTERCEPT_MEMCPY here as

  • it is unexplained why enabling interception for memcpy means we cannot use internal_memcpy in this context, and
  • this PR is supposed to be an AIX-specific change, so why have a change that reads as being platform-agnostic?

SANITIZER_INTERCEPT_MEMCPY was added in d7c6cad, which basically makes it an alias of SI_NOT_AIX. I believe this should just use SI_NOT_AIX directly (with a TODO to remove this function when REAL(memcpy) is set up to work on AIX).

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 (REAL(strnlen)) {
return REAL(strnlen)(s, maxlen);
}
Expand Down Expand Up @@ -275,7 +285,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 int *)(thread);
# else
return result ? 0 : *(uptr *)(thread);
# endif
});
}
if (result != 0) {
Expand Down Expand Up @@ -432,12 +447,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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a formatting change that should have happened on a separate PR?

INTERCEPTOR(void, _longjmp, void *env, int val) {
__asan_handle_no_return();
REAL(_longjmp)(env, val);
Expand Down Expand Up @@ -508,6 +525,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);
Expand Down Expand Up @@ -547,7 +565,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);
Expand All @@ -569,6 +589,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) {
}
return REAL(strcpy)(to, from);
}
# endif

// Windows doesn't always define the strdup identifier,
// and when it does it's a macro defined to either _strdup
Expand Down Expand Up @@ -596,7 +617,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<char*>(new_mem);
}
Expand All @@ -614,12 +635,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<char*>(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);
Expand All @@ -632,6 +654,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) {
}
return REAL(strncpy)(to, from, size);
}
# endif

template <typename Fn>
static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
Expand Down Expand Up @@ -743,7 +766,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
Comment on lines +804 to +810
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe split adding new interceptors out to a separate PR and focus this PR on compatibility changes to existing sanitizer code.


# if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
Expand Down Expand Up @@ -804,10 +835,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);
# if ASAN_INTERCEPT___STRDUP
ASAN_INTERCEPT_FUNC(__strdup);
Expand All @@ -827,7 +862,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);
Expand Down Expand Up @@ -894,7 +931,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

Expand Down
150 changes: 87 additions & 63 deletions compiler-rt/lib/asan/asan_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@ void InitializePlatformInterceptors();
// really defined to replace libc functions.
#if !SANITIZER_FUCHSIA

# 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
# define ASAN_INTERCEPT_INDEX 1
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
# 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
# define ASAN_INTERCEPT__LONGJMP 0
# define ASAN_INTERCEPT_INDEX 0
Expand All @@ -56,73 +66,87 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_SWAPCONTEXT 0
#endif

#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_SIGLONGJMP 1
#else
# define ASAN_INTERCEPT_SIGLONGJMP 0
#endif

#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___LONGJMP_CHK 1
#else
# define ASAN_INTERCEPT___LONGJMP_CHK 0
#endif
# if !SANITIZER_WINDOWS && !SANITIZER_AIX
# define ASAN_INTERCEPT_SIGLONGJMP 1
# else
# define ASAN_INTERCEPT_SIGLONGJMP 0
# endif

#if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
# define ASAN_INTERCEPT___CXA_THROW 1
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
# else
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
# endif
#else
# define ASAN_INTERCEPT___CXA_THROW 0
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
#endif
# if SANITIZER_GLIBC
# define ASAN_INTERCEPT___LONGJMP_CHK 1
# else
# define ASAN_INTERCEPT___LONGJMP_CHK 0
# endif

# if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
# define ASAN_INTERCEPT___CXA_THROW 1
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
# else
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
# endif
# else
# define ASAN_INTERCEPT___CXA_THROW 0
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
# endif

# if !SANITIZER_WINDOWS && !SANITIZER_AIX
# define ASAN_INTERCEPT___CXA_ATEXIT 1
# else
# define ASAN_INTERCEPT___CXA_ATEXIT 0
# endif

#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT___CXA_ATEXIT 1
#else
# define ASAN_INTERCEPT___CXA_ATEXIT 0
#endif
# if SANITIZER_AIX
# define ASAN_INTERCEPT_EXIT 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is special about AIX that we need it for AIX and not other platforms? What happens on AIX if we don't have this?

# else
# define ASAN_INTERCEPT_EXIT 0
# endif

#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
#else
# define ASAN_INTERCEPT_ATEXIT 0
#endif
# if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
# else
# define ASAN_INTERCEPT_ATEXIT 0
# endif

#if SANITIZER_GLIBC
# define ASAN_INTERCEPT___STRDUP 1
#else
# define ASAN_INTERCEPT___STRDUP 0
#endif
# if SANITIZER_GLIBC
# define ASAN_INTERCEPT___STRDUP 1
# else
# define ASAN_INTERCEPT___STRDUP 0
# endif

#if SANITIZER_GLIBC && ASAN_INTERCEPT_PTHREAD_CREATE
# define ASAN_INTERCEPT_TIMEDJOIN 1
# define ASAN_INTERCEPT_TRYJOIN 1
#else
# define ASAN_INTERCEPT_TIMEDJOIN 0
# define ASAN_INTERCEPT_TRYJOIN 0
#endif
# if SANITIZER_GLIBC && ASAN_INTERCEPT_PTHREAD_CREATE
# define ASAN_INTERCEPT_TIMEDJOIN 1
# define ASAN_INTERCEPT_TRYJOIN 1
# else
# define ASAN_INTERCEPT_TIMEDJOIN 0
# define ASAN_INTERCEPT_TRYJOIN 0
# endif

#if SANITIZER_LINUX && \
(defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
# define ASAN_INTERCEPT_VFORK 1
#else
# define ASAN_INTERCEPT_VFORK 0
#endif
# 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)
# define ASAN_INTERCEPT_VFORK 1
# else
# define ASAN_INTERCEPT_VFORK 0
# endif

#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
#else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
#endif
# if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
# else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
# endif

DECLARE_REAL(int, memcmp, const void *a1, const void *a2, SIZE_T size)
DECLARE_REAL(char*, strchr, const char *str, int c)
Expand Down
9 changes: 8 additions & 1 deletion compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@

using namespace __asan;

// AIX does not intercept memcpy, so we have to use internal_memcpy.
#if !SANITIZER_AIX
# define ASAN_MEMCPY_RETURN(to, from, size) REAL(memcpy)(to, from, size)
#else
# define ASAN_MEMCPY_RETURN(to, from, size) internal_memcpy(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.
Expand All @@ -36,7 +43,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.
Expand Down
Loading
Loading