xref: /freebsd/contrib/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
168d75effSDimitry Andric //===-- msan_interceptors.cpp ---------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of MemorySanitizer.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // Interceptors for standard library functions.
1268d75effSDimitry Andric //
1368d75effSDimitry Andric // FIXME: move as many interceptors as possible into
1468d75effSDimitry Andric // sanitizer_common/sanitizer_common_interceptors.h
1568d75effSDimitry Andric //===----------------------------------------------------------------------===//
1668d75effSDimitry Andric 
1706c3fb27SDimitry Andric #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
1806c3fb27SDimitry Andric 
1968d75effSDimitry Andric #include "interception/interception.h"
2068d75effSDimitry Andric #include "msan.h"
2168d75effSDimitry Andric #include "msan_chained_origin_depot.h"
2206c3fb27SDimitry Andric #include "msan_dl.h"
2368d75effSDimitry Andric #include "msan_origin.h"
24349cc55cSDimitry Andric #include "msan_poisoning.h"
2568d75effSDimitry Andric #include "msan_report.h"
2668d75effSDimitry Andric #include "msan_thread.h"
2768d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
28349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_allocator_dlsym.h"
2968d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h"
3068d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h"
3168d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
3268d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h"
33349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_errno_codes.h"
34349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_glibc_version.h"
3568d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h"
3668d75effSDimitry Andric #include "sanitizer_common/sanitizer_linux.h"
37349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
38349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_platform_limits_posix.h"
39349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h"
4068d75effSDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h"
4168d75effSDimitry Andric #include "sanitizer_common/sanitizer_vector.h"
4268d75effSDimitry Andric 
4368d75effSDimitry Andric #if SANITIZER_NETBSD
4468d75effSDimitry Andric #define fstat __fstat50
4568d75effSDimitry Andric #define gettimeofday __gettimeofday50
4668d75effSDimitry Andric #define getrusage __getrusage50
4768d75effSDimitry Andric #define tzset __tzset50
4868d75effSDimitry Andric #endif
4968d75effSDimitry Andric 
5068d75effSDimitry Andric #include <stdarg.h>
5168d75effSDimitry Andric // ACHTUNG! No other system header includes in this file.
5268d75effSDimitry Andric // Ideally, we should get rid of stdarg.h as well.
5368d75effSDimitry Andric 
5468d75effSDimitry Andric using namespace __msan;
5568d75effSDimitry Andric 
5668d75effSDimitry Andric using __sanitizer::memory_order;
5768d75effSDimitry Andric using __sanitizer::atomic_load;
5868d75effSDimitry Andric using __sanitizer::atomic_store;
5968d75effSDimitry Andric using __sanitizer::atomic_uintptr_t;
6068d75effSDimitry Andric 
6168d75effSDimitry Andric DECLARE_REAL(SIZE_T, strlen, const char *s)
6268d75effSDimitry Andric DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
6368d75effSDimitry Andric DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n)
6468d75effSDimitry Andric DECLARE_REAL(void *, memset, void *dest, int c, uptr n)
6568d75effSDimitry Andric 
6668d75effSDimitry Andric // True if this is a nested interceptor.
6768d75effSDimitry Andric static THREADLOCAL int in_interceptor_scope;
6868d75effSDimitry Andric 
__msan_scoped_disable_interceptor_checks()6968d75effSDimitry Andric void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope; }
__msan_scoped_enable_interceptor_checks()7068d75effSDimitry Andric void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope; }
7168d75effSDimitry Andric 
7268d75effSDimitry Andric struct InterceptorScope {
InterceptorScopeInterceptorScope7368d75effSDimitry Andric   InterceptorScope() { ++in_interceptor_scope; }
~InterceptorScopeInterceptorScope7468d75effSDimitry Andric   ~InterceptorScope() { --in_interceptor_scope; }
7568d75effSDimitry Andric };
7668d75effSDimitry Andric 
IsInInterceptorScope()7768d75effSDimitry Andric bool IsInInterceptorScope() {
7868d75effSDimitry Andric   return in_interceptor_scope;
7968d75effSDimitry Andric }
8068d75effSDimitry Andric 
81349cc55cSDimitry Andric struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc82349cc55cSDimitry Andric   static bool UseImpl() { return !msan_inited; }
83349cc55cSDimitry Andric };
8468d75effSDimitry Andric 
8568d75effSDimitry Andric #define ENSURE_MSAN_INITED() do { \
8668d75effSDimitry Andric   CHECK(!msan_init_is_running); \
8768d75effSDimitry Andric   if (!msan_inited) { \
8868d75effSDimitry Andric     __msan_init(); \
8968d75effSDimitry Andric   } \
9068d75effSDimitry Andric } while (0)
9168d75effSDimitry Andric 
9268d75effSDimitry Andric // Check that [x, x+n) range is unpoisoned.
9368d75effSDimitry Andric #define CHECK_UNPOISONED_0(x, n)                                  \
9468d75effSDimitry Andric   do {                                                            \
9568d75effSDimitry Andric     sptr __offset = __msan_test_shadow(x, n);                     \
9681ad6265SDimitry Andric     if (__msan::IsInSymbolizerOrUnwider())                        \
9781ad6265SDimitry Andric       break;                                                      \
9868d75effSDimitry Andric     if (__offset >= 0 && __msan::flags()->report_umrs) {          \
9906c3fb27SDimitry Andric       GET_CALLER_PC_BP;                                           \
10068d75effSDimitry Andric       ReportUMRInsideAddressRange(__func__, x, n, __offset);      \
10168d75effSDimitry Andric       __msan::PrintWarningWithOrigin(                             \
10268d75effSDimitry Andric           pc, bp, __msan_get_origin((const char *)x + __offset)); \
10368d75effSDimitry Andric       if (__msan::flags()->halt_on_error) {                       \
10468d75effSDimitry Andric         Printf("Exiting\n");                                      \
10568d75effSDimitry Andric         Die();                                                    \
10668d75effSDimitry Andric       }                                                           \
10768d75effSDimitry Andric     }                                                             \
10868d75effSDimitry Andric   } while (0)
10968d75effSDimitry Andric 
11068d75effSDimitry Andric // Check that [x, x+n) range is unpoisoned unless we are in a nested
11168d75effSDimitry Andric // interceptor.
11268d75effSDimitry Andric #define CHECK_UNPOISONED(x, n)                             \
11368d75effSDimitry Andric   do {                                                     \
11468d75effSDimitry Andric     if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
11568d75effSDimitry Andric   } while (0)
11668d75effSDimitry Andric 
11768d75effSDimitry Andric #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n)               \
11868d75effSDimitry Andric   CHECK_UNPOISONED((x),                                         \
11968d75effSDimitry Andric     common_flags()->strict_string_checks ? (len) + 1 : (n) )
12068d75effSDimitry Andric 
12168d75effSDimitry Andric #define CHECK_UNPOISONED_STRING(x, n)                           \
12268d75effSDimitry Andric     CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
12368d75effSDimitry Andric 
12468d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,fread_unlocked,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)12568d75effSDimitry Andric INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
12668d75effSDimitry Andric             void *file) {
12768d75effSDimitry Andric   ENSURE_MSAN_INITED();
12868d75effSDimitry Andric   SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
12968d75effSDimitry Andric   if (res > 0)
13068d75effSDimitry Andric     __msan_unpoison(ptr, res *size);
13168d75effSDimitry Andric   return res;
13268d75effSDimitry Andric }
13368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
13468d75effSDimitry Andric #else
13568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
13668d75effSDimitry Andric #endif
13768d75effSDimitry Andric 
13868d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(void *,mempcpy,void * dest,const void * src,SIZE_T n)13968d75effSDimitry Andric INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
14068d75effSDimitry Andric   return (char *)__msan_memcpy(dest, src, n) + n;
14168d75effSDimitry Andric }
14268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
14368d75effSDimitry Andric #else
14468d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MEMPCPY
14568d75effSDimitry Andric #endif
14668d75effSDimitry Andric 
INTERCEPTOR(void *,memccpy,void * dest,const void * src,int c,SIZE_T n)14768d75effSDimitry Andric INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
14868d75effSDimitry Andric   ENSURE_MSAN_INITED();
14968d75effSDimitry Andric   void *res = REAL(memccpy)(dest, src, c, n);
15068d75effSDimitry Andric   CHECK(!res || (res >= dest && res <= (char *)dest + n));
15168d75effSDimitry Andric   SIZE_T sz = res ? (char *)res - (char *)dest : n;
15268d75effSDimitry Andric   CHECK_UNPOISONED(src, sz);
15368d75effSDimitry Andric   __msan_unpoison(dest, sz);
15468d75effSDimitry Andric   return res;
15568d75effSDimitry Andric }
15668d75effSDimitry Andric 
INTERCEPTOR(void *,bcopy,const void * src,void * dest,SIZE_T n)15768d75effSDimitry Andric INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
15868d75effSDimitry Andric   return __msan_memmove(dest, src, n);
15968d75effSDimitry Andric }
16068d75effSDimitry Andric 
INTERCEPTOR(int,posix_memalign,void ** memptr,SIZE_T alignment,SIZE_T size)16168d75effSDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
16268d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
16368d75effSDimitry Andric   CHECK_NE(memptr, 0);
16468d75effSDimitry Andric   int res = msan_posix_memalign(memptr, alignment, size, &stack);
16568d75effSDimitry Andric   if (!res)
16668d75effSDimitry Andric     __msan_unpoison(memptr, sizeof(*memptr));
16768d75effSDimitry Andric   return res;
16868d75effSDimitry Andric }
16968d75effSDimitry Andric 
17068d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void *,memalign,SIZE_T alignment,SIZE_T size)17168d75effSDimitry Andric INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {
17268d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
17368d75effSDimitry Andric   return msan_memalign(alignment, size, &stack);
17468d75effSDimitry Andric }
17568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
17668d75effSDimitry Andric #else
17768d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MEMALIGN
17868d75effSDimitry Andric #endif
17968d75effSDimitry Andric 
INTERCEPTOR(void *,aligned_alloc,SIZE_T alignment,SIZE_T size)18068d75effSDimitry Andric INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
18168d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
18268d75effSDimitry Andric   return msan_aligned_alloc(alignment, size, &stack);
18368d75effSDimitry Andric }
18468d75effSDimitry Andric 
18568d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(void *,__libc_memalign,SIZE_T alignment,SIZE_T size)18668d75effSDimitry Andric INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {
18768d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
18868d75effSDimitry Andric   void *ptr = msan_memalign(alignment, size, &stack);
18968d75effSDimitry Andric   if (ptr)
19068d75effSDimitry Andric     DTLS_on_libc_memalign(ptr, size);
19168d75effSDimitry Andric   return ptr;
19268d75effSDimitry Andric }
19368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
19468d75effSDimitry Andric #else
19568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
19668d75effSDimitry Andric #endif
19768d75effSDimitry Andric 
INTERCEPTOR(void *,valloc,SIZE_T size)19868d75effSDimitry Andric INTERCEPTOR(void *, valloc, SIZE_T size) {
19968d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
20068d75effSDimitry Andric   return msan_valloc(size, &stack);
20168d75effSDimitry Andric }
20268d75effSDimitry Andric 
20368d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void *,pvalloc,SIZE_T size)20468d75effSDimitry Andric INTERCEPTOR(void *, pvalloc, SIZE_T size) {
20568d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
20668d75effSDimitry Andric   return msan_pvalloc(size, &stack);
20768d75effSDimitry Andric }
20868d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
20968d75effSDimitry Andric #else
21068d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PVALLOC
21168d75effSDimitry Andric #endif
21268d75effSDimitry Andric 
INTERCEPTOR(void,free,void * ptr)21368d75effSDimitry Andric INTERCEPTOR(void, free, void *ptr) {
214349cc55cSDimitry Andric   if (UNLIKELY(!ptr))
215349cc55cSDimitry Andric     return;
216349cc55cSDimitry Andric   if (DlsymAlloc::PointerIsMine(ptr))
217349cc55cSDimitry Andric     return DlsymAlloc::Free(ptr);
21868d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
21968d75effSDimitry Andric   MsanDeallocate(&stack, ptr);
22068d75effSDimitry Andric }
22168d75effSDimitry Andric 
22268d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void,cfree,void * ptr)22368d75effSDimitry Andric INTERCEPTOR(void, cfree, void *ptr) {
224349cc55cSDimitry Andric   if (UNLIKELY(!ptr))
225349cc55cSDimitry Andric     return;
226349cc55cSDimitry Andric   if (DlsymAlloc::PointerIsMine(ptr))
227349cc55cSDimitry Andric     return DlsymAlloc::Free(ptr);
22868d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
22968d75effSDimitry Andric   MsanDeallocate(&stack, ptr);
23068d75effSDimitry Andric }
23168d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
23268d75effSDimitry Andric #else
23368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_CFREE
23468d75effSDimitry Andric #endif
23568d75effSDimitry Andric 
23668d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)23768d75effSDimitry Andric INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
23868d75effSDimitry Andric   return __sanitizer_get_allocated_size(ptr);
23968d75effSDimitry Andric }
24068d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
24168d75effSDimitry Andric   INTERCEPT_FUNCTION(malloc_usable_size)
24268d75effSDimitry Andric #else
24368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
24468d75effSDimitry Andric #endif
24568d75effSDimitry Andric 
2465f757f3fSDimitry Andric #if (!SANITIZER_FREEBSD && !SANITIZER_NETBSD) || __GLIBC_PREREQ(2, 33)
2475f757f3fSDimitry Andric template <class T>
clear_mallinfo(T * sret)2485f757f3fSDimitry Andric static NOINLINE void clear_mallinfo(T *sret) {
2495f757f3fSDimitry Andric   ENSURE_MSAN_INITED();
2505f757f3fSDimitry Andric   internal_memset(sret, 0, sizeof(*sret));
25168d75effSDimitry Andric   __msan_unpoison(sret, sizeof(*sret));
25268d75effSDimitry Andric }
2535f757f3fSDimitry Andric #endif
2545f757f3fSDimitry Andric 
2555f757f3fSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
2565f757f3fSDimitry Andric // Interceptors use NRVO and assume that sret will be pre-allocated in
2575f757f3fSDimitry Andric // caller frame.
258*0fca6ea1SDimitry Andric INTERCEPTOR(__sanitizer_struct_mallinfo, mallinfo,) {
2595f757f3fSDimitry Andric   __sanitizer_struct_mallinfo sret;
2605f757f3fSDimitry Andric   clear_mallinfo(&sret);
2615f757f3fSDimitry Andric   return sret;
2625f757f3fSDimitry Andric }
26368d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
26468d75effSDimitry Andric #else
26568d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_MALLINFO
26668d75effSDimitry Andric #endif
26768d75effSDimitry Andric 
2685f757f3fSDimitry Andric #if __GLIBC_PREREQ(2, 33)
INTERCEPTOR(__sanitizer_struct_mallinfo2,mallinfo2)2695f757f3fSDimitry Andric INTERCEPTOR(__sanitizer_struct_mallinfo2, mallinfo2) {
2705f757f3fSDimitry Andric   __sanitizer_struct_mallinfo2 sret;
2715f757f3fSDimitry Andric   clear_mallinfo(&sret);
2725f757f3fSDimitry Andric   return sret;
2735f757f3fSDimitry Andric }
2745f757f3fSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_MALLINFO2 INTERCEPT_FUNCTION(mallinfo2)
2755f757f3fSDimitry Andric #else
2765f757f3fSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_MALLINFO2
2775f757f3fSDimitry Andric #endif
2785f757f3fSDimitry Andric 
27968d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,mallopt,int cmd,int value)28068d75effSDimitry Andric INTERCEPTOR(int, mallopt, int cmd, int value) {
28168d75effSDimitry Andric   return 0;
28268d75effSDimitry Andric }
28368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
28468d75effSDimitry Andric #else
28568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOPT
28668d75effSDimitry Andric #endif
28768d75effSDimitry Andric 
28868d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(void,malloc_stats,void)28968d75effSDimitry Andric INTERCEPTOR(void, malloc_stats, void) {
29068d75effSDimitry Andric   // FIXME: implement, but don't call REAL(malloc_stats)!
29168d75effSDimitry Andric }
29268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
29368d75effSDimitry Andric #else
29468d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
29568d75effSDimitry Andric #endif
29668d75effSDimitry Andric 
INTERCEPTOR(char *,strcpy,char * dest,const char * src)29768d75effSDimitry Andric INTERCEPTOR(char *, strcpy, char *dest, const char *src) {
29868d75effSDimitry Andric   ENSURE_MSAN_INITED();
29968d75effSDimitry Andric   GET_STORE_STACK_TRACE;
300349cc55cSDimitry Andric   SIZE_T n = internal_strlen(src);
30168d75effSDimitry Andric   CHECK_UNPOISONED_STRING(src + n, 0);
30268d75effSDimitry Andric   char *res = REAL(strcpy)(dest, src);
30368d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, n + 1, &stack);
30468d75effSDimitry Andric   return res;
30568d75effSDimitry Andric }
30668d75effSDimitry Andric 
INTERCEPTOR(char *,strncpy,char * dest,const char * src,SIZE_T n)30768d75effSDimitry Andric INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {
30868d75effSDimitry Andric   ENSURE_MSAN_INITED();
30968d75effSDimitry Andric   GET_STORE_STACK_TRACE;
310349cc55cSDimitry Andric   SIZE_T copy_size = internal_strnlen(src, n);
31168d75effSDimitry Andric   if (copy_size < n)
31268d75effSDimitry Andric     copy_size++;  // trailing \0
31368d75effSDimitry Andric   char *res = REAL(strncpy)(dest, src, n);
31468d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, copy_size, &stack);
31568d75effSDimitry Andric   __msan_unpoison(dest + copy_size, n - copy_size);
31668d75effSDimitry Andric   return res;
31768d75effSDimitry Andric }
31868d75effSDimitry Andric 
31968d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(char *,stpcpy,char * dest,const char * src)32068d75effSDimitry Andric INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {
32168d75effSDimitry Andric   ENSURE_MSAN_INITED();
32268d75effSDimitry Andric   GET_STORE_STACK_TRACE;
323349cc55cSDimitry Andric   SIZE_T n = internal_strlen(src);
32468d75effSDimitry Andric   CHECK_UNPOISONED_STRING(src + n, 0);
32568d75effSDimitry Andric   char *res = REAL(stpcpy)(dest, src);
32668d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, n + 1, &stack);
32768d75effSDimitry Andric   return res;
32868d75effSDimitry Andric }
329bdd1243dSDimitry Andric 
INTERCEPTOR(char *,stpncpy,char * dest,const char * src,SIZE_T n)330bdd1243dSDimitry Andric INTERCEPTOR(char *, stpncpy, char *dest, const char *src, SIZE_T n) {
331bdd1243dSDimitry Andric   ENSURE_MSAN_INITED();
332bdd1243dSDimitry Andric   GET_STORE_STACK_TRACE;
333bdd1243dSDimitry Andric   SIZE_T copy_size = Min(n, internal_strnlen(src, n) + 1);
334bdd1243dSDimitry Andric   char *res = REAL(stpncpy)(dest, src, n);
335bdd1243dSDimitry Andric   CopyShadowAndOrigin(dest, src, copy_size, &stack);
336bdd1243dSDimitry Andric   __msan_unpoison(dest + copy_size, n - copy_size);
337bdd1243dSDimitry Andric   return res;
338bdd1243dSDimitry Andric }
33968d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
340bdd1243dSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
34168d75effSDimitry Andric #else
34268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_STPCPY
343bdd1243dSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_STPNCPY
34468d75effSDimitry Andric #endif
34568d75effSDimitry Andric 
INTERCEPTOR(char *,strdup,char * src)34668d75effSDimitry Andric INTERCEPTOR(char *, strdup, char *src) {
34768d75effSDimitry Andric   ENSURE_MSAN_INITED();
34868d75effSDimitry Andric   GET_STORE_STACK_TRACE;
34968d75effSDimitry Andric   // On FreeBSD strdup() leverages strlen().
35068d75effSDimitry Andric   InterceptorScope interceptor_scope;
351349cc55cSDimitry Andric   SIZE_T n = internal_strlen(src);
35268d75effSDimitry Andric   CHECK_UNPOISONED_STRING(src + n, 0);
35368d75effSDimitry Andric   char *res = REAL(strdup)(src);
35468d75effSDimitry Andric   CopyShadowAndOrigin(res, src, n + 1, &stack);
35568d75effSDimitry Andric   return res;
35668d75effSDimitry Andric }
35768d75effSDimitry Andric 
35868d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(char *,__strdup,char * src)35968d75effSDimitry Andric INTERCEPTOR(char *, __strdup, char *src) {
36068d75effSDimitry Andric   ENSURE_MSAN_INITED();
36168d75effSDimitry Andric   GET_STORE_STACK_TRACE;
362349cc55cSDimitry Andric   SIZE_T n = internal_strlen(src);
36368d75effSDimitry Andric   CHECK_UNPOISONED_STRING(src + n, 0);
36468d75effSDimitry Andric   char *res = REAL(__strdup)(src);
36568d75effSDimitry Andric   CopyShadowAndOrigin(res, src, n + 1, &stack);
36668d75effSDimitry Andric   return res;
36768d75effSDimitry Andric }
36868d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
36968d75effSDimitry Andric #else
37068d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___STRDUP
37168d75effSDimitry Andric #endif
37268d75effSDimitry Andric 
37368d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(char *,gcvt,double number,SIZE_T ndigit,char * buf)37468d75effSDimitry Andric INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
37568d75effSDimitry Andric   ENSURE_MSAN_INITED();
37668d75effSDimitry Andric   char *res = REAL(gcvt)(number, ndigit, buf);
377349cc55cSDimitry Andric   SIZE_T n = internal_strlen(buf);
37868d75effSDimitry Andric   __msan_unpoison(buf, n + 1);
37968d75effSDimitry Andric   return res;
38068d75effSDimitry Andric }
38168d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
38268d75effSDimitry Andric #else
38368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_GCVT
38468d75effSDimitry Andric #endif
38568d75effSDimitry Andric 
INTERCEPTOR(char *,strcat,char * dest,const char * src)38668d75effSDimitry Andric INTERCEPTOR(char *, strcat, char *dest, const char *src) {
38768d75effSDimitry Andric   ENSURE_MSAN_INITED();
38868d75effSDimitry Andric   GET_STORE_STACK_TRACE;
389349cc55cSDimitry Andric   SIZE_T src_size = internal_strlen(src);
390349cc55cSDimitry Andric   SIZE_T dest_size = internal_strlen(dest);
39168d75effSDimitry Andric   CHECK_UNPOISONED_STRING(src + src_size, 0);
39268d75effSDimitry Andric   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
39368d75effSDimitry Andric   char *res = REAL(strcat)(dest, src);
39468d75effSDimitry Andric   CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
39568d75effSDimitry Andric   return res;
39668d75effSDimitry Andric }
39768d75effSDimitry Andric 
INTERCEPTOR(char *,strncat,char * dest,const char * src,SIZE_T n)39868d75effSDimitry Andric INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {
39968d75effSDimitry Andric   ENSURE_MSAN_INITED();
40068d75effSDimitry Andric   GET_STORE_STACK_TRACE;
401349cc55cSDimitry Andric   SIZE_T dest_size = internal_strlen(dest);
402349cc55cSDimitry Andric   SIZE_T copy_size = internal_strnlen(src, n);
40368d75effSDimitry Andric   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
40468d75effSDimitry Andric   char *res = REAL(strncat)(dest, src, n);
40568d75effSDimitry Andric   CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
40668d75effSDimitry Andric   __msan_unpoison(dest + dest_size + copy_size, 1); // \0
40768d75effSDimitry Andric   return res;
40868d75effSDimitry Andric }
40968d75effSDimitry Andric 
41068d75effSDimitry Andric // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
41168d75effSDimitry Andric // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
41268d75effSDimitry Andric #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
41368d75effSDimitry Andric   ENSURE_MSAN_INITED();                             \
41468d75effSDimitry Andric   ret_type res = REAL(func)(__VA_ARGS__);           \
41568d75effSDimitry Andric   __msan_unpoison(endptr, sizeof(*endptr));         \
41668d75effSDimitry Andric   return res;
41768d75effSDimitry Andric 
4185f757f3fSDimitry Andric // On s390x, long double return values are passed via implicit reference,
4195f757f3fSDimitry Andric // which needs to be unpoisoned.  We make the implicit pointer explicit.
4205f757f3fSDimitry Andric #define INTERCEPTOR_STRTO_SRET_BODY(func, sret, ...) \
4215f757f3fSDimitry Andric   ENSURE_MSAN_INITED();                              \
4225f757f3fSDimitry Andric   REAL(func)(sret, __VA_ARGS__);                     \
4235f757f3fSDimitry Andric   __msan_unpoison(sret, sizeof(*sret));              \
4245f757f3fSDimitry Andric   __msan_unpoison(endptr, sizeof(*endptr));
4255f757f3fSDimitry Andric 
42668d75effSDimitry Andric #define INTERCEPTOR_STRTO(ret_type, func, char_type)                       \
42768d75effSDimitry Andric   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
42868d75effSDimitry Andric     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr);                  \
42968d75effSDimitry Andric   }
43068d75effSDimitry Andric 
4315f757f3fSDimitry Andric #define INTERCEPTOR_STRTO_SRET(ret_type, func, char_type)                \
4325f757f3fSDimitry Andric   INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr,         \
4335f757f3fSDimitry Andric               char_type **endptr) {                                      \
4345f757f3fSDimitry Andric     INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr);               \
4355f757f3fSDimitry Andric   }
4365f757f3fSDimitry Andric 
43768d75effSDimitry Andric #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)                \
43868d75effSDimitry Andric   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
43968d75effSDimitry Andric               int base) {                                                \
44068d75effSDimitry Andric     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base);          \
44168d75effSDimitry Andric   }
44268d75effSDimitry Andric 
44368d75effSDimitry Andric #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type)                 \
44468d75effSDimitry Andric   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
44568d75effSDimitry Andric               void *loc) {                                               \
44668d75effSDimitry Andric     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc);           \
44768d75effSDimitry Andric   }
44868d75effSDimitry Andric 
4495f757f3fSDimitry Andric #define INTERCEPTOR_STRTO_SRET_LOC(ret_type, func, char_type)            \
4505f757f3fSDimitry Andric   INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr,         \
4515f757f3fSDimitry Andric               char_type **endptr, void *loc) {                           \
4525f757f3fSDimitry Andric     INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr, loc);          \
4535f757f3fSDimitry Andric   }
4545f757f3fSDimitry Andric 
45568d75effSDimitry Andric #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type)            \
45668d75effSDimitry Andric   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
45768d75effSDimitry Andric               int base, void *loc) {                                     \
45868d75effSDimitry Andric     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc);     \
45968d75effSDimitry Andric   }
46068d75effSDimitry Andric 
46168d75effSDimitry Andric #if SANITIZER_NETBSD
46268d75effSDimitry Andric #define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
46368d75effSDimitry Andric   INTERCEPTOR_STRTO(ret_type, func, char_type)             \
46468d75effSDimitry Andric   INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
46568d75effSDimitry Andric 
4665f757f3fSDimitry Andric #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type)      \
4675f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET(ret_type, func, char_type)             \
4685f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type)
4695f757f3fSDimitry Andric 
47068d75effSDimitry Andric #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
47168d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
47268d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
47368d75effSDimitry Andric 
47468d75effSDimitry Andric #else
47568d75effSDimitry Andric #define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
47668d75effSDimitry Andric   INTERCEPTOR_STRTO(ret_type, func, char_type)             \
47768d75effSDimitry Andric   INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)     \
47868d75effSDimitry Andric   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
47968d75effSDimitry Andric   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
48068d75effSDimitry Andric 
4815f757f3fSDimitry Andric #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type)      \
4825f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET(ret_type, func, char_type)             \
4835f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type)     \
4845f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_l, char_type) \
4855f757f3fSDimitry Andric   INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_internal, char_type)
4865f757f3fSDimitry Andric 
48768d75effSDimitry Andric #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
48868d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
48968d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)     \
49068d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
49168d75effSDimitry Andric   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
49268d75effSDimitry Andric #endif
49368d75effSDimitry Andric 
INTERCEPTORS_STRTO(double,strtod,char)49468d75effSDimitry Andric INTERCEPTORS_STRTO(double, strtod, char)
49568d75effSDimitry Andric INTERCEPTORS_STRTO(float, strtof, char)
4965f757f3fSDimitry Andric #ifdef __s390x__
4975f757f3fSDimitry Andric INTERCEPTORS_STRTO_SRET(long double, strtold, char)
4985f757f3fSDimitry Andric #else
49968d75effSDimitry Andric INTERCEPTORS_STRTO(long double, strtold, char)
5005f757f3fSDimitry Andric #endif
50168d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(long, strtol, char)
50268d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(long long, strtoll, char)
50368d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)
50468d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)
50568d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(u64, strtouq, char)
50668d75effSDimitry Andric 
50768d75effSDimitry Andric INTERCEPTORS_STRTO(double, wcstod, wchar_t)
50868d75effSDimitry Andric INTERCEPTORS_STRTO(float, wcstof, wchar_t)
5095f757f3fSDimitry Andric #ifdef __s390x__
5105f757f3fSDimitry Andric INTERCEPTORS_STRTO_SRET(long double, wcstold, wchar_t)
5115f757f3fSDimitry Andric #else
51268d75effSDimitry Andric INTERCEPTORS_STRTO(long double, wcstold, wchar_t)
5135f757f3fSDimitry Andric #endif
51468d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)
51568d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
51668d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
51768d75effSDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)
51868d75effSDimitry Andric 
5198a4dda33SDimitry Andric #if SANITIZER_GLIBC
5208a4dda33SDimitry Andric INTERCEPTORS_STRTO(double, __isoc23_strtod, char)
5218a4dda33SDimitry Andric INTERCEPTORS_STRTO(float, __isoc23_strtof, char)
5225f757f3fSDimitry Andric #ifdef __s390x__
5235f757f3fSDimitry Andric INTERCEPTORS_STRTO_SRET(long double, __isoc23_strtold, char)
5245f757f3fSDimitry Andric #else
5258a4dda33SDimitry Andric INTERCEPTORS_STRTO(long double, __isoc23_strtold, char)
5265f757f3fSDimitry Andric #endif
5278a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol, char)
5288a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll, char)
5298a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul, char)
5308a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull, char)
5318a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(u64, __isoc23_strtouq, char)
5328a4dda33SDimitry Andric 
5338a4dda33SDimitry Andric INTERCEPTORS_STRTO(double, __isoc23_wcstod, wchar_t)
5348a4dda33SDimitry Andric INTERCEPTORS_STRTO(float, __isoc23_wcstof, wchar_t)
5355f757f3fSDimitry Andric #ifdef __s390x__
5365f757f3fSDimitry Andric INTERCEPTORS_STRTO_SRET(long double, __isoc23_wcstold, wchar_t)
5375f757f3fSDimitry Andric #else
5388a4dda33SDimitry Andric INTERCEPTORS_STRTO(long double, __isoc23_wcstold, wchar_t)
5395f757f3fSDimitry Andric #endif
5408a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol, wchar_t)
5418a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll, wchar_t)
5428a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul, wchar_t)
5438a4dda33SDimitry Andric INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull, wchar_t)
5448a4dda33SDimitry Andric #endif
5458a4dda33SDimitry Andric 
54668d75effSDimitry Andric #if SANITIZER_NETBSD
54768d75effSDimitry Andric #define INTERCEPT_STRTO(func) \
54868d75effSDimitry Andric   INTERCEPT_FUNCTION(func); \
54968d75effSDimitry Andric   INTERCEPT_FUNCTION(func##_l);
55068d75effSDimitry Andric #else
55168d75effSDimitry Andric #define INTERCEPT_STRTO(func) \
55268d75effSDimitry Andric   INTERCEPT_FUNCTION(func); \
55368d75effSDimitry Andric   INTERCEPT_FUNCTION(func##_l); \
55468d75effSDimitry Andric   INTERCEPT_FUNCTION(__##func##_l); \
55568d75effSDimitry Andric   INTERCEPT_FUNCTION(__##func##_internal);
5565f757f3fSDimitry Andric 
5575f757f3fSDimitry Andric #define INTERCEPT_STRTO_VER(func, ver) \
5585f757f3fSDimitry Andric   INTERCEPT_FUNCTION_VER(func, ver); \
5595f757f3fSDimitry Andric   INTERCEPT_FUNCTION_VER(func##_l, ver); \
5605f757f3fSDimitry Andric   INTERCEPT_FUNCTION_VER(__##func##_l, ver); \
5615f757f3fSDimitry Andric   INTERCEPT_FUNCTION_VER(__##func##_internal, ver);
56268d75effSDimitry Andric #endif
56368d75effSDimitry Andric 
56468d75effSDimitry Andric 
56568d75effSDimitry Andric // FIXME: support *wprintf in common format interceptors.
56668d75effSDimitry Andric INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
56768d75effSDimitry Andric   ENSURE_MSAN_INITED();
56868d75effSDimitry Andric   int res = REAL(vswprintf)(str, size, format, ap);
56968d75effSDimitry Andric   if (res >= 0) {
57068d75effSDimitry Andric     __msan_unpoison(str, 4 * (res + 1));
57168d75effSDimitry Andric   }
57268d75effSDimitry Andric   return res;
57368d75effSDimitry Andric }
57468d75effSDimitry Andric 
INTERCEPTOR(int,swprintf,void * str,uptr size,void * format,...)57568d75effSDimitry Andric INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
57668d75effSDimitry Andric   ENSURE_MSAN_INITED();
57768d75effSDimitry Andric   va_list ap;
57868d75effSDimitry Andric   va_start(ap, format);
57968d75effSDimitry Andric   int res = vswprintf(str, size, format, ap);
58068d75effSDimitry Andric   va_end(ap);
58168d75effSDimitry Andric   return res;
58268d75effSDimitry Andric }
58368d75effSDimitry Andric 
58468d75effSDimitry Andric #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
58568d75effSDimitry Andric   ENSURE_MSAN_INITED();                                              \
58668d75effSDimitry Andric   InterceptorScope interceptor_scope;                                \
58768d75effSDimitry Andric   ret_type res = REAL(func)(s, __VA_ARGS__);                         \
58868d75effSDimitry Andric   if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1));          \
58968d75effSDimitry Andric   return res;
59068d75effSDimitry Andric 
INTERCEPTOR(SIZE_T,strftime,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm)59168d75effSDimitry Andric INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
59268d75effSDimitry Andric             __sanitizer_tm *tm) {
59368d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
59468d75effSDimitry Andric }
59568d75effSDimitry Andric 
INTERCEPTOR(SIZE_T,strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)59668d75effSDimitry Andric INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
59768d75effSDimitry Andric             __sanitizer_tm *tm, void *loc) {
59868d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
59968d75effSDimitry Andric }
60068d75effSDimitry Andric 
60168d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,__strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)60268d75effSDimitry Andric INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
60368d75effSDimitry Andric             __sanitizer_tm *tm, void *loc) {
60468d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
60568d75effSDimitry Andric                             loc);
60668d75effSDimitry Andric }
60768d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
60868d75effSDimitry Andric #else
60968d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
61068d75effSDimitry Andric #endif
61168d75effSDimitry Andric 
INTERCEPTOR(SIZE_T,wcsftime,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm)61268d75effSDimitry Andric INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
61368d75effSDimitry Andric             __sanitizer_tm *tm) {
61468d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
61568d75effSDimitry Andric }
61668d75effSDimitry Andric 
INTERCEPTOR(SIZE_T,wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)61768d75effSDimitry Andric INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
61868d75effSDimitry Andric             __sanitizer_tm *tm, void *loc) {
61968d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
62068d75effSDimitry Andric                             loc);
62168d75effSDimitry Andric }
62268d75effSDimitry Andric 
62368d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,__wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)62468d75effSDimitry Andric INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
62568d75effSDimitry Andric             __sanitizer_tm *tm, void *loc) {
62668d75effSDimitry Andric   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
62768d75effSDimitry Andric                             loc);
62868d75effSDimitry Andric }
62968d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
63068d75effSDimitry Andric #else
63168d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
63268d75effSDimitry Andric #endif
63368d75effSDimitry Andric 
INTERCEPTOR(int,mbtowc,wchar_t * dest,const char * src,SIZE_T n)63468d75effSDimitry Andric INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
63568d75effSDimitry Andric   ENSURE_MSAN_INITED();
63668d75effSDimitry Andric   int res = REAL(mbtowc)(dest, src, n);
63768d75effSDimitry Andric   if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
63868d75effSDimitry Andric   return res;
63968d75effSDimitry Andric }
64068d75effSDimitry Andric 
INTERCEPTOR(SIZE_T,mbrtowc,wchar_t * dest,const char * src,SIZE_T n,void * ps)64168d75effSDimitry Andric INTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n,
64268d75effSDimitry Andric             void *ps) {
64368d75effSDimitry Andric   ENSURE_MSAN_INITED();
64468d75effSDimitry Andric   SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
64568d75effSDimitry Andric   if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
64668d75effSDimitry Andric   return res;
64768d75effSDimitry Andric }
64868d75effSDimitry Andric 
64968d75effSDimitry Andric // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
INTERCEPTOR(wchar_t *,wmemcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)65068d75effSDimitry Andric INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
65168d75effSDimitry Andric   ENSURE_MSAN_INITED();
65268d75effSDimitry Andric   GET_STORE_STACK_TRACE;
65368d75effSDimitry Andric   wchar_t *res = REAL(wmemcpy)(dest, src, n);
65468d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
65568d75effSDimitry Andric   return res;
65668d75effSDimitry Andric }
65768d75effSDimitry Andric 
65868d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(wchar_t *,wmempcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)65968d75effSDimitry Andric INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
66068d75effSDimitry Andric   ENSURE_MSAN_INITED();
66168d75effSDimitry Andric   GET_STORE_STACK_TRACE;
66268d75effSDimitry Andric   wchar_t *res = REAL(wmempcpy)(dest, src, n);
66368d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
66468d75effSDimitry Andric   return res;
66568d75effSDimitry Andric }
66668d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
66768d75effSDimitry Andric #else
66868d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
66968d75effSDimitry Andric #endif
67068d75effSDimitry Andric 
INTERCEPTOR(wchar_t *,wmemset,wchar_t * s,wchar_t c,SIZE_T n)67168d75effSDimitry Andric INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
67268d75effSDimitry Andric   CHECK(MEM_IS_APP(s));
67368d75effSDimitry Andric   ENSURE_MSAN_INITED();
67468d75effSDimitry Andric   wchar_t *res = REAL(wmemset)(s, c, n);
67568d75effSDimitry Andric   __msan_unpoison(s, n * sizeof(wchar_t));
67668d75effSDimitry Andric   return res;
67768d75effSDimitry Andric }
67868d75effSDimitry Andric 
INTERCEPTOR(wchar_t *,wmemmove,wchar_t * dest,const wchar_t * src,SIZE_T n)67968d75effSDimitry Andric INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
68068d75effSDimitry Andric   ENSURE_MSAN_INITED();
68168d75effSDimitry Andric   GET_STORE_STACK_TRACE;
68268d75effSDimitry Andric   wchar_t *res = REAL(wmemmove)(dest, src, n);
68368d75effSDimitry Andric   MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
68468d75effSDimitry Andric   return res;
68568d75effSDimitry Andric }
68668d75effSDimitry Andric 
INTERCEPTOR(int,wcscmp,const wchar_t * s1,const wchar_t * s2)68768d75effSDimitry Andric INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
68868d75effSDimitry Andric   ENSURE_MSAN_INITED();
68968d75effSDimitry Andric   int res = REAL(wcscmp)(s1, s2);
69068d75effSDimitry Andric   return res;
69168d75effSDimitry Andric }
69268d75effSDimitry Andric 
INTERCEPTOR(int,gettimeofday,void * tv,void * tz)69368d75effSDimitry Andric INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
69468d75effSDimitry Andric   ENSURE_MSAN_INITED();
69568d75effSDimitry Andric   int res = REAL(gettimeofday)(tv, tz);
69668d75effSDimitry Andric   if (tv)
69768d75effSDimitry Andric     __msan_unpoison(tv, 16);
69868d75effSDimitry Andric   if (tz)
69968d75effSDimitry Andric     __msan_unpoison(tz, 8);
70068d75effSDimitry Andric   return res;
70168d75effSDimitry Andric }
70268d75effSDimitry Andric 
70368d75effSDimitry Andric #if !SANITIZER_NETBSD
INTERCEPTOR(char *,fcvt,double x,int a,int * b,int * c)70468d75effSDimitry Andric INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
70568d75effSDimitry Andric   ENSURE_MSAN_INITED();
70668d75effSDimitry Andric   char *res = REAL(fcvt)(x, a, b, c);
70768d75effSDimitry Andric   __msan_unpoison(b, sizeof(*b));
70868d75effSDimitry Andric   __msan_unpoison(c, sizeof(*c));
709349cc55cSDimitry Andric   if (res)
710349cc55cSDimitry Andric     __msan_unpoison(res, internal_strlen(res) + 1);
71168d75effSDimitry Andric   return res;
71268d75effSDimitry Andric }
71368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
71468d75effSDimitry Andric #else
71568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FCVT
71668d75effSDimitry Andric #endif
71768d75effSDimitry Andric 
INTERCEPTOR(char *,getenv,char * name)71868d75effSDimitry Andric INTERCEPTOR(char *, getenv, char *name) {
71968d75effSDimitry Andric   if (msan_init_is_running)
72068d75effSDimitry Andric     return REAL(getenv)(name);
72168d75effSDimitry Andric   ENSURE_MSAN_INITED();
72268d75effSDimitry Andric   char *res = REAL(getenv)(name);
723349cc55cSDimitry Andric   if (res)
724349cc55cSDimitry Andric     __msan_unpoison(res, internal_strlen(res) + 1);
72568d75effSDimitry Andric   return res;
72668d75effSDimitry Andric }
72768d75effSDimitry Andric 
72868d75effSDimitry Andric extern char **environ;
72968d75effSDimitry Andric 
UnpoisonEnviron()73068d75effSDimitry Andric static void UnpoisonEnviron() {
73168d75effSDimitry Andric   char **envp = environ;
73268d75effSDimitry Andric   for (; *envp; ++envp) {
73368d75effSDimitry Andric     __msan_unpoison(envp, sizeof(*envp));
734349cc55cSDimitry Andric     __msan_unpoison(*envp, internal_strlen(*envp) + 1);
73568d75effSDimitry Andric   }
73668d75effSDimitry Andric   // Trailing NULL pointer.
73768d75effSDimitry Andric   __msan_unpoison(envp, sizeof(*envp));
73868d75effSDimitry Andric }
73968d75effSDimitry Andric 
INTERCEPTOR(int,setenv,const char * name,const char * value,int overwrite)74068d75effSDimitry Andric INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
74168d75effSDimitry Andric   ENSURE_MSAN_INITED();
74268d75effSDimitry Andric   CHECK_UNPOISONED_STRING(name, 0);
74368d75effSDimitry Andric   int res = REAL(setenv)(name, value, overwrite);
74468d75effSDimitry Andric   if (!res) UnpoisonEnviron();
74568d75effSDimitry Andric   return res;
74668d75effSDimitry Andric }
74768d75effSDimitry Andric 
INTERCEPTOR(int,putenv,char * string)74868d75effSDimitry Andric INTERCEPTOR(int, putenv, char *string) {
74968d75effSDimitry Andric   ENSURE_MSAN_INITED();
75068d75effSDimitry Andric   int res = REAL(putenv)(string);
75168d75effSDimitry Andric   if (!res) UnpoisonEnviron();
75268d75effSDimitry Andric   return res;
75368d75effSDimitry Andric }
75468d75effSDimitry Andric 
755349cc55cSDimitry Andric #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
756349cc55cSDimitry Andric #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat,int fd,void * buf)75768d75effSDimitry Andric INTERCEPTOR(int, fstat, int fd, void *buf) {
75868d75effSDimitry Andric   ENSURE_MSAN_INITED();
75968d75effSDimitry Andric   int res = REAL(fstat)(fd, buf);
76068d75effSDimitry Andric   if (!res)
76168d75effSDimitry Andric     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
76268d75effSDimitry Andric   return res;
76368d75effSDimitry Andric }
764349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
76568d75effSDimitry Andric #else
76668d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FSTAT
76768d75effSDimitry Andric #endif
76868d75effSDimitry Andric 
76981ad6265SDimitry Andric #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat64,int fd,void * buf)77081ad6265SDimitry Andric INTERCEPTOR(int, fstat64, int fd, void *buf) {
77181ad6265SDimitry Andric   ENSURE_MSAN_INITED();
77281ad6265SDimitry Andric   int res = REAL(fstat64)(fd, buf);
77381ad6265SDimitry Andric   if (!res)
77481ad6265SDimitry Andric     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
77581ad6265SDimitry Andric   return res;
77681ad6265SDimitry Andric }
77781ad6265SDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
77881ad6265SDimitry Andric #else
77981ad6265SDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTAT64
78081ad6265SDimitry Andric #endif
78181ad6265SDimitry Andric 
7821fd87a68SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat,int magic,int fd,void * buf)78368d75effSDimitry Andric INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
78468d75effSDimitry Andric   ENSURE_MSAN_INITED();
78568d75effSDimitry Andric   int res = REAL(__fxstat)(magic, fd, buf);
78668d75effSDimitry Andric   if (!res)
78768d75effSDimitry Andric     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
78868d75effSDimitry Andric   return res;
78968d75effSDimitry Andric }
790349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
79168d75effSDimitry Andric #else
79268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___FXSTAT
79368d75effSDimitry Andric #endif
79468d75effSDimitry Andric 
7951fd87a68SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat64,int magic,int fd,void * buf)79668d75effSDimitry Andric INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
79768d75effSDimitry Andric   ENSURE_MSAN_INITED();
79868d75effSDimitry Andric   int res = REAL(__fxstat64)(magic, fd, buf);
79968d75effSDimitry Andric   if (!res)
80068d75effSDimitry Andric     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
80168d75effSDimitry Andric   return res;
80268d75effSDimitry Andric }
803349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
80468d75effSDimitry Andric #else
80568d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTAT64
80668d75effSDimitry Andric #endif
80768d75effSDimitry Andric 
808349cc55cSDimitry Andric #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat,int fd,char * pathname,void * buf,int flags)80968d75effSDimitry Andric INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
81068d75effSDimitry Andric   ENSURE_MSAN_INITED();
81168d75effSDimitry Andric   int res = REAL(fstatat)(fd, pathname, buf, flags);
81268d75effSDimitry Andric   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
81368d75effSDimitry Andric   return res;
81468d75effSDimitry Andric }
815349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
81668d75effSDimitry Andric #else
817349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTATAT
818349cc55cSDimitry Andric #endif
819349cc55cSDimitry Andric 
82081ad6265SDimitry Andric #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat64,int fd,char * pathname,void * buf,int flags)82181ad6265SDimitry Andric INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) {
82281ad6265SDimitry Andric   ENSURE_MSAN_INITED();
82381ad6265SDimitry Andric   int res = REAL(fstatat64)(fd, pathname, buf, flags);
82481ad6265SDimitry Andric   if (!res)
82581ad6265SDimitry Andric     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
82681ad6265SDimitry Andric   return res;
82781ad6265SDimitry Andric }
82881ad6265SDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
82981ad6265SDimitry Andric #else
83081ad6265SDimitry Andric #  define MSAN_MAYBE_INTERCEPT_FSTATAT64
83181ad6265SDimitry Andric #endif
83281ad6265SDimitry Andric 
8331fd87a68SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat,int magic,int fd,char * pathname,void * buf,int flags)83468d75effSDimitry Andric INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
83568d75effSDimitry Andric             int flags) {
83668d75effSDimitry Andric   ENSURE_MSAN_INITED();
83768d75effSDimitry Andric   int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
83868d75effSDimitry Andric   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
83968d75effSDimitry Andric   return res;
84068d75effSDimitry Andric }
841349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
842349cc55cSDimitry Andric #else
843349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTATAT
84468d75effSDimitry Andric #endif
84568d75effSDimitry Andric 
8461fd87a68SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat64,int magic,int fd,char * pathname,void * buf,int flags)84768d75effSDimitry Andric INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
84868d75effSDimitry Andric             int flags) {
84968d75effSDimitry Andric   ENSURE_MSAN_INITED();
85068d75effSDimitry Andric   int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
85168d75effSDimitry Andric   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
85268d75effSDimitry Andric   return res;
85368d75effSDimitry Andric }
854349cc55cSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
85568d75effSDimitry Andric #else
85668d75effSDimitry Andric #  define MSAN_MAYBE_INTERCEPT___FXSTATAT64
85768d75effSDimitry Andric #endif
85868d75effSDimitry Andric 
INTERCEPTOR(int,pipe,int pipefd[2])85968d75effSDimitry Andric INTERCEPTOR(int, pipe, int pipefd[2]) {
86068d75effSDimitry Andric   if (msan_init_is_running)
86168d75effSDimitry Andric     return REAL(pipe)(pipefd);
86268d75effSDimitry Andric   ENSURE_MSAN_INITED();
86368d75effSDimitry Andric   int res = REAL(pipe)(pipefd);
86468d75effSDimitry Andric   if (!res)
86568d75effSDimitry Andric     __msan_unpoison(pipefd, sizeof(int[2]));
86668d75effSDimitry Andric   return res;
86768d75effSDimitry Andric }
86868d75effSDimitry Andric 
INTERCEPTOR(int,pipe2,int pipefd[2],int flags)86968d75effSDimitry Andric INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
87068d75effSDimitry Andric   ENSURE_MSAN_INITED();
87168d75effSDimitry Andric   int res = REAL(pipe2)(pipefd, flags);
87268d75effSDimitry Andric   if (!res)
87368d75effSDimitry Andric     __msan_unpoison(pipefd, sizeof(int[2]));
87468d75effSDimitry Andric   return res;
87568d75effSDimitry Andric }
87668d75effSDimitry Andric 
INTERCEPTOR(int,socketpair,int domain,int type,int protocol,int sv[2])87768d75effSDimitry Andric INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
87868d75effSDimitry Andric   ENSURE_MSAN_INITED();
87968d75effSDimitry Andric   int res = REAL(socketpair)(domain, type, protocol, sv);
88068d75effSDimitry Andric   if (!res)
88168d75effSDimitry Andric     __msan_unpoison(sv, sizeof(int[2]));
88268d75effSDimitry Andric   return res;
88368d75effSDimitry Andric }
88468d75effSDimitry Andric 
88568d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(char *,fgets_unlocked,char * s,int size,void * stream)88668d75effSDimitry Andric INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
88768d75effSDimitry Andric   ENSURE_MSAN_INITED();
88868d75effSDimitry Andric   char *res = REAL(fgets_unlocked)(s, size, stream);
88968d75effSDimitry Andric   if (res)
890349cc55cSDimitry Andric     __msan_unpoison(s, internal_strlen(s) + 1);
89168d75effSDimitry Andric   return res;
89268d75effSDimitry Andric }
89368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
89468d75effSDimitry Andric #else
89568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
89668d75effSDimitry Andric #endif
89768d75effSDimitry Andric 
89868d75effSDimitry Andric #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim)  \
89968d75effSDimitry Andric   if (msan_init_is_running)                               \
90068d75effSDimitry Andric     return REAL(getrlimit)(resource, rlim);               \
90168d75effSDimitry Andric   ENSURE_MSAN_INITED();                                   \
90268d75effSDimitry Andric   int res = REAL(func)(resource, rlim);                   \
90368d75effSDimitry Andric   if (!res)                                               \
90468d75effSDimitry Andric     __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
90568d75effSDimitry Andric   return res
90668d75effSDimitry Andric 
INTERCEPTOR(int,getrlimit,int resource,void * rlim)90768d75effSDimitry Andric INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
90868d75effSDimitry Andric   INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim);
90968d75effSDimitry Andric }
91068d75effSDimitry Andric 
91168d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,__getrlimit,int resource,void * rlim)91268d75effSDimitry Andric INTERCEPTOR(int, __getrlimit, int resource, void *rlim) {
91368d75effSDimitry Andric   INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim);
91468d75effSDimitry Andric }
91568d75effSDimitry Andric 
INTERCEPTOR(int,getrlimit64,int resource,void * rlim)91668d75effSDimitry Andric INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
91768d75effSDimitry Andric   if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
91868d75effSDimitry Andric   ENSURE_MSAN_INITED();
91968d75effSDimitry Andric   int res = REAL(getrlimit64)(resource, rlim);
92068d75effSDimitry Andric   if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
92168d75effSDimitry Andric   return res;
92268d75effSDimitry Andric }
92368d75effSDimitry Andric 
INTERCEPTOR(int,prlimit,int pid,int resource,void * new_rlimit,void * old_rlimit)92468d75effSDimitry Andric INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
92568d75effSDimitry Andric             void *old_rlimit) {
92668d75effSDimitry Andric   if (msan_init_is_running)
92768d75effSDimitry Andric     return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
92868d75effSDimitry Andric   ENSURE_MSAN_INITED();
92968d75effSDimitry Andric   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
93068d75effSDimitry Andric   int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
93168d75effSDimitry Andric   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
93268d75effSDimitry Andric   return res;
93368d75effSDimitry Andric }
93468d75effSDimitry Andric 
INTERCEPTOR(int,prlimit64,int pid,int resource,void * new_rlimit,void * old_rlimit)93568d75effSDimitry Andric INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
93668d75effSDimitry Andric             void *old_rlimit) {
93768d75effSDimitry Andric   if (msan_init_is_running)
93868d75effSDimitry Andric     return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
93968d75effSDimitry Andric   ENSURE_MSAN_INITED();
94068d75effSDimitry Andric   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
94168d75effSDimitry Andric   int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
94268d75effSDimitry Andric   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
94368d75effSDimitry Andric   return res;
94468d75effSDimitry Andric }
94568d75effSDimitry Andric 
94668d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
94768d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
94868d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
94968d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
95068d75effSDimitry Andric #else
95168d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
95268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
95368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PRLIMIT
95468d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
95568d75effSDimitry Andric #endif
95668d75effSDimitry Andric 
INTERCEPTOR(int,gethostname,char * name,SIZE_T len)95768d75effSDimitry Andric INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
95868d75effSDimitry Andric   ENSURE_MSAN_INITED();
95968d75effSDimitry Andric   int res = REAL(gethostname)(name, len);
960e8d8bef9SDimitry Andric   if (!res || (res == -1 && errno == errno_ENAMETOOLONG)) {
961349cc55cSDimitry Andric     SIZE_T real_len = internal_strnlen(name, len);
96268d75effSDimitry Andric     if (real_len < len)
96368d75effSDimitry Andric       ++real_len;
96468d75effSDimitry Andric     __msan_unpoison(name, real_len);
96568d75effSDimitry Andric   }
96668d75effSDimitry Andric   return res;
96768d75effSDimitry Andric }
96868d75effSDimitry Andric 
96968d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)97068d75effSDimitry Andric INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
97168d75effSDimitry Andric     int timeout) {
97268d75effSDimitry Andric   ENSURE_MSAN_INITED();
97368d75effSDimitry Andric   int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
97468d75effSDimitry Andric   if (res > 0) {
97568d75effSDimitry Andric     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
97668d75effSDimitry Andric   }
97768d75effSDimitry Andric   return res;
97868d75effSDimitry Andric }
97968d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
98068d75effSDimitry Andric #else
98168d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
98268d75effSDimitry Andric #endif
98368d75effSDimitry Andric 
98468d75effSDimitry Andric #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_pwait,int epfd,void * events,int maxevents,int timeout,void * sigmask)98568d75effSDimitry Andric INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
98668d75effSDimitry Andric     int timeout, void *sigmask) {
98768d75effSDimitry Andric   ENSURE_MSAN_INITED();
98868d75effSDimitry Andric   int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
98968d75effSDimitry Andric   if (res > 0) {
99068d75effSDimitry Andric     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
99168d75effSDimitry Andric   }
99268d75effSDimitry Andric   return res;
99368d75effSDimitry Andric }
99468d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
99568d75effSDimitry Andric #else
99668d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
99768d75effSDimitry Andric #endif
99868d75effSDimitry Andric 
INTERCEPTOR(void *,calloc,SIZE_T nmemb,SIZE_T size)99968d75effSDimitry Andric INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
100068d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
1001349cc55cSDimitry Andric   if (DlsymAlloc::Use())
1002349cc55cSDimitry Andric     return DlsymAlloc::Callocate(nmemb, size);
100368d75effSDimitry Andric   return msan_calloc(nmemb, size, &stack);
100468d75effSDimitry Andric }
100568d75effSDimitry Andric 
INTERCEPTOR(void *,realloc,void * ptr,SIZE_T size)100668d75effSDimitry Andric INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
1007349cc55cSDimitry Andric   if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
1008349cc55cSDimitry Andric     return DlsymAlloc::Realloc(ptr, size);
100968d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
101068d75effSDimitry Andric   return msan_realloc(ptr, size, &stack);
101168d75effSDimitry Andric }
101268d75effSDimitry Andric 
INTERCEPTOR(void *,reallocarray,void * ptr,SIZE_T nmemb,SIZE_T size)101368d75effSDimitry Andric INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
101468d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
101568d75effSDimitry Andric   return msan_reallocarray(ptr, nmemb, size, &stack);
101668d75effSDimitry Andric }
101768d75effSDimitry Andric 
INTERCEPTOR(void *,malloc,SIZE_T size)101868d75effSDimitry Andric INTERCEPTOR(void *, malloc, SIZE_T size) {
1019349cc55cSDimitry Andric   if (DlsymAlloc::Use())
1020349cc55cSDimitry Andric     return DlsymAlloc::Allocate(size);
102168d75effSDimitry Andric   GET_MALLOC_STACK_TRACE;
102268d75effSDimitry Andric   return msan_malloc(size, &stack);
102368d75effSDimitry Andric }
102468d75effSDimitry Andric 
__msan_allocated_memory(const void * data,uptr size)102568d75effSDimitry Andric void __msan_allocated_memory(const void *data, uptr size) {
102668d75effSDimitry Andric   if (flags()->poison_in_malloc) {
1027349cc55cSDimitry Andric     GET_MALLOC_STACK_TRACE;
102868d75effSDimitry Andric     stack.tag = STACK_TRACE_TAG_POISON;
102968d75effSDimitry Andric     PoisonMemory(data, size, &stack);
103068d75effSDimitry Andric   }
103168d75effSDimitry Andric }
103268d75effSDimitry Andric 
__msan_copy_shadow(void * dest,const void * src,uptr n)103368d75effSDimitry Andric void __msan_copy_shadow(void *dest, const void *src, uptr n) {
103468d75effSDimitry Andric   GET_STORE_STACK_TRACE;
103568d75effSDimitry Andric   MoveShadowAndOrigin(dest, src, n, &stack);
103668d75effSDimitry Andric }
103768d75effSDimitry Andric 
__sanitizer_dtor_callback(const void * data,uptr size)103868d75effSDimitry Andric void __sanitizer_dtor_callback(const void *data, uptr size) {
103968d75effSDimitry Andric   if (flags()->poison_in_dtor) {
1040349cc55cSDimitry Andric     GET_MALLOC_STACK_TRACE;
104168d75effSDimitry Andric     stack.tag = STACK_TRACE_TAG_POISON;
104268d75effSDimitry Andric     PoisonMemory(data, size, &stack);
104368d75effSDimitry Andric   }
104468d75effSDimitry Andric }
104568d75effSDimitry Andric 
__sanitizer_dtor_callback_fields(const void * data,uptr size)1046bdd1243dSDimitry Andric void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
1047bdd1243dSDimitry Andric   if (flags()->poison_in_dtor) {
1048bdd1243dSDimitry Andric     GET_MALLOC_STACK_TRACE;
1049bdd1243dSDimitry Andric     stack.tag = STACK_TRACE_TAG_FIELDS;
1050bdd1243dSDimitry Andric     PoisonMemory(data, size, &stack);
1051bdd1243dSDimitry Andric   }
1052bdd1243dSDimitry Andric }
1053bdd1243dSDimitry Andric 
__sanitizer_dtor_callback_vptr(const void * data)1054bdd1243dSDimitry Andric void __sanitizer_dtor_callback_vptr(const void *data) {
1055bdd1243dSDimitry Andric   if (flags()->poison_in_dtor) {
1056bdd1243dSDimitry Andric     GET_MALLOC_STACK_TRACE;
1057bdd1243dSDimitry Andric     stack.tag = STACK_TRACE_TAG_VPTR;
1058bdd1243dSDimitry Andric     PoisonMemory(data, sizeof(void *), &stack);
1059bdd1243dSDimitry Andric   }
1060bdd1243dSDimitry Andric }
1061bdd1243dSDimitry Andric 
106268d75effSDimitry Andric template <class Mmap>
mmap_interceptor(Mmap real_mmap,void * addr,SIZE_T length,int prot,int flags,int fd,OFF64_T offset)106368d75effSDimitry Andric static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
106468d75effSDimitry Andric                               int prot, int flags, int fd, OFF64_T offset) {
10655ffd83dbSDimitry Andric   SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
10665ffd83dbSDimitry Andric   void *end_addr = (char *)addr + (rounded_length - 1);
10675ffd83dbSDimitry Andric   if (addr && (!MEM_IS_APP(addr) || !MEM_IS_APP(end_addr))) {
106868d75effSDimitry Andric     if (flags & map_fixed) {
106968d75effSDimitry Andric       errno = errno_EINVAL;
107068d75effSDimitry Andric       return (void *)-1;
107168d75effSDimitry Andric     } else {
107268d75effSDimitry Andric       addr = nullptr;
107368d75effSDimitry Andric     }
107468d75effSDimitry Andric   }
107568d75effSDimitry Andric   void *res = real_mmap(addr, length, prot, flags, fd, offset);
10765ffd83dbSDimitry Andric   if (res != (void *)-1) {
10775ffd83dbSDimitry Andric     void *end_res = (char *)res + (rounded_length - 1);
10785ffd83dbSDimitry Andric     if (MEM_IS_APP(res) && MEM_IS_APP(end_res)) {
10795ffd83dbSDimitry Andric       __msan_unpoison(res, rounded_length);
10805ffd83dbSDimitry Andric     } else {
10815ffd83dbSDimitry Andric       // Application has attempted to map more memory than is supported by
10825ffd83dbSDimitry Andric       // MSAN. Act as if we ran out of memory.
10835ffd83dbSDimitry Andric       internal_munmap(res, length);
10845ffd83dbSDimitry Andric       errno = errno_ENOMEM;
10855ffd83dbSDimitry Andric       return (void *)-1;
10865ffd83dbSDimitry Andric     }
10875ffd83dbSDimitry Andric   }
108868d75effSDimitry Andric   return res;
108968d75effSDimitry Andric }
109068d75effSDimitry Andric 
INTERCEPTOR(int,getrusage,int who,void * usage)109168d75effSDimitry Andric INTERCEPTOR(int, getrusage, int who, void *usage) {
109268d75effSDimitry Andric   ENSURE_MSAN_INITED();
109368d75effSDimitry Andric   int res = REAL(getrusage)(who, usage);
109468d75effSDimitry Andric   if (res == 0) {
109568d75effSDimitry Andric     __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
109668d75effSDimitry Andric   }
109768d75effSDimitry Andric   return res;
109868d75effSDimitry Andric }
109968d75effSDimitry Andric 
110068d75effSDimitry Andric class SignalHandlerScope {
110168d75effSDimitry Andric  public:
SignalHandlerScope()110268d75effSDimitry Andric   SignalHandlerScope() {
110368d75effSDimitry Andric     if (MsanThread *t = GetCurrentThread())
110468d75effSDimitry Andric       t->EnterSignalHandler();
110568d75effSDimitry Andric   }
~SignalHandlerScope()110668d75effSDimitry Andric   ~SignalHandlerScope() {
110768d75effSDimitry Andric     if (MsanThread *t = GetCurrentThread())
110868d75effSDimitry Andric       t->LeaveSignalHandler();
110968d75effSDimitry Andric   }
111068d75effSDimitry Andric };
111168d75effSDimitry Andric 
111268d75effSDimitry Andric // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
111368d75effSDimitry Andric // Access to sigactions[] is gone with relaxed atomics to avoid data race with
111468d75effSDimitry Andric // the signal handler.
111568d75effSDimitry Andric const int kMaxSignals = 1024;
111668d75effSDimitry Andric static atomic_uintptr_t sigactions[kMaxSignals];
111768d75effSDimitry Andric static StaticSpinMutex sigactions_mu;
111868d75effSDimitry Andric 
SignalHandler(int signo)111968d75effSDimitry Andric static void SignalHandler(int signo) {
112068d75effSDimitry Andric   SignalHandlerScope signal_handler_scope;
112168d75effSDimitry Andric   ScopedThreadLocalStateBackup stlsb;
112268d75effSDimitry Andric   UnpoisonParam(1);
112368d75effSDimitry Andric 
112468d75effSDimitry Andric   typedef void (*signal_cb)(int x);
112568d75effSDimitry Andric   signal_cb cb =
112668d75effSDimitry Andric       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
112768d75effSDimitry Andric   cb(signo);
112868d75effSDimitry Andric }
112968d75effSDimitry Andric 
SignalAction(int signo,void * si,void * uc)113068d75effSDimitry Andric static void SignalAction(int signo, void *si, void *uc) {
113168d75effSDimitry Andric   SignalHandlerScope signal_handler_scope;
113268d75effSDimitry Andric   ScopedThreadLocalStateBackup stlsb;
113368d75effSDimitry Andric   UnpoisonParam(3);
113468d75effSDimitry Andric   __msan_unpoison(si, sizeof(__sanitizer_sigaction));
113504eeddc0SDimitry Andric   __msan_unpoison(uc, ucontext_t_sz(uc));
113668d75effSDimitry Andric 
113768d75effSDimitry Andric   typedef void (*sigaction_cb)(int, void *, void *);
113868d75effSDimitry Andric   sigaction_cb cb =
113968d75effSDimitry Andric       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
114068d75effSDimitry Andric   cb(signo, si, uc);
114104eeddc0SDimitry Andric   CHECK_UNPOISONED(uc, ucontext_t_sz(uc));
114268d75effSDimitry Andric }
114368d75effSDimitry Andric 
read_sigaction(const __sanitizer_sigaction * act)114468d75effSDimitry Andric static void read_sigaction(const __sanitizer_sigaction *act) {
114568d75effSDimitry Andric   CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
114668d75effSDimitry Andric   if (act->sa_flags & __sanitizer::sa_siginfo)
114768d75effSDimitry Andric     CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
114868d75effSDimitry Andric   else
114968d75effSDimitry Andric     CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
115068d75effSDimitry Andric   CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
115168d75effSDimitry Andric }
115268d75effSDimitry Andric 
115368d75effSDimitry Andric extern "C" int pthread_attr_init(void *attr);
115468d75effSDimitry Andric extern "C" int pthread_attr_destroy(void *attr);
115568d75effSDimitry Andric 
MsanThreadStartFunc(void * arg)115668d75effSDimitry Andric static void *MsanThreadStartFunc(void *arg) {
115768d75effSDimitry Andric   MsanThread *t = (MsanThread *)arg;
115868d75effSDimitry Andric   SetCurrentThread(t);
1159349cc55cSDimitry Andric   t->Init();
1160349cc55cSDimitry Andric   SetSigProcMask(&t->starting_sigset_, nullptr);
116168d75effSDimitry Andric   return t->ThreadStart();
116268d75effSDimitry Andric }
116368d75effSDimitry Andric 
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)116468d75effSDimitry Andric INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
116568d75effSDimitry Andric             void * param) {
116668d75effSDimitry Andric   ENSURE_MSAN_INITED(); // for GetTlsSize()
116768d75effSDimitry Andric   __sanitizer_pthread_attr_t myattr;
116868d75effSDimitry Andric   if (!attr) {
116968d75effSDimitry Andric     pthread_attr_init(&myattr);
117068d75effSDimitry Andric     attr = &myattr;
117168d75effSDimitry Andric   }
117268d75effSDimitry Andric 
117368d75effSDimitry Andric   AdjustStackSize(attr);
117468d75effSDimitry Andric 
117568d75effSDimitry Andric   MsanThread *t = MsanThread::Create(callback, param);
1176349cc55cSDimitry Andric   ScopedBlockSignals block(&t->starting_sigset_);
117768d75effSDimitry Andric   int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
117868d75effSDimitry Andric 
117968d75effSDimitry Andric   if (attr == &myattr)
118068d75effSDimitry Andric     pthread_attr_destroy(&myattr);
118168d75effSDimitry Andric   if (!res) {
118268d75effSDimitry Andric     __msan_unpoison(th, __sanitizer::pthread_t_sz);
118368d75effSDimitry Andric   }
118468d75effSDimitry Andric   return res;
118568d75effSDimitry Andric }
118668d75effSDimitry Andric 
INTERCEPTOR(int,pthread_key_create,__sanitizer_pthread_key_t * key,void (* dtor)(void * value))118768d75effSDimitry Andric INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
118868d75effSDimitry Andric             void (*dtor)(void *value)) {
118968d75effSDimitry Andric   if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
119068d75effSDimitry Andric   ENSURE_MSAN_INITED();
119168d75effSDimitry Andric   int res = REAL(pthread_key_create)(key, dtor);
119268d75effSDimitry Andric   if (!res && key)
119368d75effSDimitry Andric     __msan_unpoison(key, sizeof(*key));
119468d75effSDimitry Andric   return res;
119568d75effSDimitry Andric }
119668d75effSDimitry Andric 
119768d75effSDimitry Andric #if SANITIZER_NETBSD
1198480093f4SDimitry Andric INTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m,
1199480093f4SDimitry Andric             void (*dtor)(void *value))
120006c3fb27SDimitry Andric ALIAS(WRAP(pthread_key_create));
120168d75effSDimitry Andric #endif
120268d75effSDimitry Andric 
INTERCEPTOR(int,pthread_join,void * thread,void ** retval)120306c3fb27SDimitry Andric INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
120468d75effSDimitry Andric   ENSURE_MSAN_INITED();
120506c3fb27SDimitry Andric   int res = REAL(pthread_join)(thread, retval);
120668d75effSDimitry Andric   if (!res && retval)
120768d75effSDimitry Andric     __msan_unpoison(retval, sizeof(*retval));
120868d75effSDimitry Andric   return res;
120968d75effSDimitry Andric }
121068d75effSDimitry Andric 
121106c3fb27SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,pthread_tryjoin_np,void * thread,void ** retval)121206c3fb27SDimitry Andric INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **retval) {
121306c3fb27SDimitry Andric   ENSURE_MSAN_INITED();
121406c3fb27SDimitry Andric   int res = REAL(pthread_tryjoin_np)(thread, retval);
121506c3fb27SDimitry Andric   if (!res && retval)
121606c3fb27SDimitry Andric     __msan_unpoison(retval, sizeof(*retval));
121706c3fb27SDimitry Andric   return res;
121806c3fb27SDimitry Andric }
121906c3fb27SDimitry Andric 
INTERCEPTOR(int,pthread_timedjoin_np,void * thread,void ** retval,const struct timespec * abstime)122006c3fb27SDimitry Andric INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **retval,
122106c3fb27SDimitry Andric             const struct timespec *abstime) {
122206c3fb27SDimitry Andric   int res = REAL(pthread_timedjoin_np)(thread, retval, abstime);
122306c3fb27SDimitry Andric   if (!res && retval)
122406c3fb27SDimitry Andric     __msan_unpoison(retval, sizeof(*retval));
122506c3fb27SDimitry Andric   return res;
122606c3fb27SDimitry Andric }
122706c3fb27SDimitry Andric #endif
122806c3fb27SDimitry Andric 
1229*0fca6ea1SDimitry Andric DEFINE_INTERNAL_PTHREAD_FUNCTIONS
12300eae32dcSDimitry Andric 
123168d75effSDimitry Andric extern char *tzname[2];
123268d75effSDimitry Andric 
INTERCEPTOR(void,tzset,int fake)123368d75effSDimitry Andric INTERCEPTOR(void, tzset, int fake) {
123468d75effSDimitry Andric   ENSURE_MSAN_INITED();
123568d75effSDimitry Andric   InterceptorScope interceptor_scope;
123668d75effSDimitry Andric   REAL(tzset)(fake);
123768d75effSDimitry Andric   if (tzname[0])
1238349cc55cSDimitry Andric     __msan_unpoison(tzname[0], internal_strlen(tzname[0]) + 1);
123968d75effSDimitry Andric   if (tzname[1])
1240349cc55cSDimitry Andric     __msan_unpoison(tzname[1], internal_strlen(tzname[1]) + 1);
124168d75effSDimitry Andric   return;
124268d75effSDimitry Andric }
124368d75effSDimitry Andric 
124468d75effSDimitry Andric struct MSanAtExitRecord {
124568d75effSDimitry Andric   void (*func)(void *arg);
124668d75effSDimitry Andric   void *arg;
124768d75effSDimitry Andric };
124868d75effSDimitry Andric 
124968d75effSDimitry Andric struct InterceptorContext {
1250349cc55cSDimitry Andric   Mutex atexit_mu;
125168d75effSDimitry Andric   Vector<struct MSanAtExitRecord *> AtExitStack;
125268d75effSDimitry Andric 
InterceptorContextInterceptorContext125368d75effSDimitry Andric   InterceptorContext()
125468d75effSDimitry Andric       : AtExitStack() {
125568d75effSDimitry Andric   }
125668d75effSDimitry Andric };
125768d75effSDimitry Andric 
1258*0fca6ea1SDimitry Andric alignas(64) static char interceptor_placeholder[sizeof(InterceptorContext)];
interceptor_ctx()125968d75effSDimitry Andric InterceptorContext *interceptor_ctx() {
126068d75effSDimitry Andric   return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
126168d75effSDimitry Andric }
126268d75effSDimitry Andric 
MSanAtExitWrapper()126368d75effSDimitry Andric void MSanAtExitWrapper() {
126468d75effSDimitry Andric   MSanAtExitRecord *r;
126568d75effSDimitry Andric   {
1266349cc55cSDimitry Andric     Lock l(&interceptor_ctx()->atexit_mu);
126768d75effSDimitry Andric 
126868d75effSDimitry Andric     uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
126968d75effSDimitry Andric     r = interceptor_ctx()->AtExitStack[element];
127068d75effSDimitry Andric     interceptor_ctx()->AtExitStack.PopBack();
127168d75effSDimitry Andric   }
127268d75effSDimitry Andric 
127368d75effSDimitry Andric   UnpoisonParam(1);
127468d75effSDimitry Andric   ((void(*)())r->func)();
127568d75effSDimitry Andric   InternalFree(r);
127668d75effSDimitry Andric }
127768d75effSDimitry Andric 
MSanCxaAtExitWrapper(void * arg)127868d75effSDimitry Andric void MSanCxaAtExitWrapper(void *arg) {
127968d75effSDimitry Andric   UnpoisonParam(1);
128068d75effSDimitry Andric   MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
128168d75effSDimitry Andric   // libc before 2.27 had race which caused occasional double handler execution
128268d75effSDimitry Andric   // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
128368d75effSDimitry Andric   if (!r->func)
128468d75effSDimitry Andric     return;
128568d75effSDimitry Andric   r->func(r->arg);
128668d75effSDimitry Andric   r->func = nullptr;
128768d75effSDimitry Andric }
128868d75effSDimitry Andric 
128968d75effSDimitry Andric static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso);
129068d75effSDimitry Andric 
129168d75effSDimitry Andric // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)129268d75effSDimitry Andric INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
129368d75effSDimitry Andric             void *dso_handle) {
129468d75effSDimitry Andric   if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
129568d75effSDimitry Andric   return setup_at_exit_wrapper((void(*)())func, arg, dso_handle);
129668d75effSDimitry Andric }
129768d75effSDimitry Andric 
129868d75effSDimitry Andric // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,atexit,void (* func)())129968d75effSDimitry Andric INTERCEPTOR(int, atexit, void (*func)()) {
1300349cc55cSDimitry Andric   // Avoid calling real atexit as it is unreachable on at least on Linux.
130168d75effSDimitry Andric   if (msan_init_is_running)
130268d75effSDimitry Andric     return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0);
130368d75effSDimitry Andric   return setup_at_exit_wrapper((void(*)())func, 0, 0);
130468d75effSDimitry Andric }
130568d75effSDimitry Andric 
setup_at_exit_wrapper(void (* f)(),void * arg,void * dso)130668d75effSDimitry Andric static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) {
130768d75effSDimitry Andric   ENSURE_MSAN_INITED();
130868d75effSDimitry Andric   MSanAtExitRecord *r =
130968d75effSDimitry Andric       (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
131068d75effSDimitry Andric   r->func = (void(*)(void *a))f;
131168d75effSDimitry Andric   r->arg = arg;
131268d75effSDimitry Andric   int res;
131368d75effSDimitry Andric   if (!dso) {
131468d75effSDimitry Andric     // NetBSD does not preserve the 2nd argument if dso is equal to 0
131568d75effSDimitry Andric     // Store ctx in a local stack-like structure
131668d75effSDimitry Andric 
1317349cc55cSDimitry Andric     Lock l(&interceptor_ctx()->atexit_mu);
131868d75effSDimitry Andric 
131968d75effSDimitry Andric     res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0);
132068d75effSDimitry Andric     if (!res) {
132168d75effSDimitry Andric       interceptor_ctx()->AtExitStack.PushBack(r);
132268d75effSDimitry Andric     }
132368d75effSDimitry Andric   } else {
132468d75effSDimitry Andric     res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso);
132568d75effSDimitry Andric   }
132668d75effSDimitry Andric   return res;
132768d75effSDimitry Andric }
132868d75effSDimitry Andric 
132968d75effSDimitry Andric // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
133068d75effSDimitry Andric // with MSan.
133168d75effSDimitry Andric #if SANITIZER_LINUX
INTERCEPTOR(int,openpty,int * aparent,int * aworker,char * name,const void * termp,const void * winp)133268d75effSDimitry Andric INTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name,
133368d75effSDimitry Andric             const void *termp, const void *winp) {
133468d75effSDimitry Andric   ENSURE_MSAN_INITED();
133568d75effSDimitry Andric   InterceptorScope interceptor_scope;
133668d75effSDimitry Andric   int res = REAL(openpty)(aparent, aworker, name, termp, winp);
133768d75effSDimitry Andric   if (!res) {
133868d75effSDimitry Andric     __msan_unpoison(aparent, sizeof(*aparent));
133968d75effSDimitry Andric     __msan_unpoison(aworker, sizeof(*aworker));
134068d75effSDimitry Andric   }
134168d75effSDimitry Andric   return res;
134268d75effSDimitry Andric }
134368d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
134468d75effSDimitry Andric #else
134568d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_OPENPTY
134668d75effSDimitry Andric #endif
134768d75effSDimitry Andric 
134868d75effSDimitry Andric // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
134968d75effSDimitry Andric // with MSan.
135068d75effSDimitry Andric #if SANITIZER_LINUX
INTERCEPTOR(int,forkpty,int * aparent,char * name,const void * termp,const void * winp)135168d75effSDimitry Andric INTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp,
135268d75effSDimitry Andric             const void *winp) {
135368d75effSDimitry Andric   ENSURE_MSAN_INITED();
135468d75effSDimitry Andric   InterceptorScope interceptor_scope;
135568d75effSDimitry Andric   int res = REAL(forkpty)(aparent, name, termp, winp);
135668d75effSDimitry Andric   if (res != -1)
135768d75effSDimitry Andric     __msan_unpoison(aparent, sizeof(*aparent));
135868d75effSDimitry Andric   return res;
135968d75effSDimitry Andric }
136068d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
136168d75effSDimitry Andric #else
136268d75effSDimitry Andric #define MSAN_MAYBE_INTERCEPT_FORKPTY
136368d75effSDimitry Andric #endif
136468d75effSDimitry Andric 
136568d75effSDimitry Andric struct MSanInterceptorContext {
136668d75effSDimitry Andric   bool in_interceptor_scope;
136768d75effSDimitry Andric };
136868d75effSDimitry Andric 
136968d75effSDimitry Andric namespace __msan {
137068d75effSDimitry Andric 
OnExit()137168d75effSDimitry Andric int OnExit() {
137268d75effSDimitry Andric   // FIXME: ask frontend whether we need to return failure.
137368d75effSDimitry Andric   return 0;
137468d75effSDimitry Andric }
137568d75effSDimitry Andric 
137668d75effSDimitry Andric } // namespace __msan
137768d75effSDimitry Andric 
137868d75effSDimitry Andric // A version of CHECK_UNPOISONED using a saved scope value. Used in common
137968d75effSDimitry Andric // interceptors.
138068d75effSDimitry Andric #define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
138168d75effSDimitry Andric   do {                                                          \
138268d75effSDimitry Andric     if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
138368d75effSDimitry Andric       CHECK_UNPOISONED_0(x, n);                                 \
138468d75effSDimitry Andric   } while (0)
138568d75effSDimitry Andric 
138668d75effSDimitry Andric #define MSAN_INTERCEPT_FUNC(name)                                       \
138768d75effSDimitry Andric   do {                                                                  \
138868d75effSDimitry Andric     if (!INTERCEPT_FUNCTION(name))                                      \
1389e8d8bef9SDimitry Andric       VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
139068d75effSDimitry Andric   } while (0)
139168d75effSDimitry Andric 
139268d75effSDimitry Andric #define MSAN_INTERCEPT_FUNC_VER(name, ver)                                 \
139368d75effSDimitry Andric   do {                                                                     \
139468d75effSDimitry Andric     if (!INTERCEPT_FUNCTION_VER(name, ver))                                \
139568d75effSDimitry Andric       VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1396349cc55cSDimitry Andric               ver);                                                        \
139768d75effSDimitry Andric   } while (0)
1398fe6060f1SDimitry Andric #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)             \
1399fe6060f1SDimitry Andric   do {                                                                      \
1400fe6060f1SDimitry Andric     if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name))    \
1401fe6060f1SDimitry Andric       VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1402349cc55cSDimitry Andric               #name, ver, #name);                                           \
1403fe6060f1SDimitry Andric   } while (0)
140468d75effSDimitry Andric 
140568d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
140668d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
140768d75effSDimitry Andric   MSAN_INTERCEPT_FUNC_VER(name, ver)
1408fe6060f1SDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1409fe6060f1SDimitry Andric   MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
141068d75effSDimitry Andric #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count)  \
141168d75effSDimitry Andric   UnpoisonParam(count)
141268d75effSDimitry Andric #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
141368d75effSDimitry Andric   __msan_unpoison(ptr, size)
141468d75effSDimitry Andric #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
141568d75effSDimitry Andric   CHECK_UNPOISONED_CTX(ctx, ptr, size)
141668d75effSDimitry Andric #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
141768d75effSDimitry Andric   __msan_unpoison(ptr, size)
141868d75effSDimitry Andric #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
1419349cc55cSDimitry Andric   if (msan_init_is_running)                                   \
1420349cc55cSDimitry Andric     return REAL(func)(__VA_ARGS__);                           \
142168d75effSDimitry Andric   ENSURE_MSAN_INITED();                                       \
142268d75effSDimitry Andric   MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
142368d75effSDimitry Andric   ctx = (void *)&msan_ctx;                                    \
142468d75effSDimitry Andric   (void)ctx;                                                  \
142568d75effSDimitry Andric   InterceptorScope interceptor_scope;                         \
1426349cc55cSDimitry Andric   __msan_unpoison(__errno_location(), sizeof(int));
142768d75effSDimitry Andric #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
142868d75effSDimitry Andric   do {                                            \
142968d75effSDimitry Andric   } while (false)
143068d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
143168d75effSDimitry Andric   do {                                         \
143268d75effSDimitry Andric   } while (false)
143368d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
143468d75effSDimitry Andric   do {                                         \
143568d75effSDimitry Andric   } while (false)
143668d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
143768d75effSDimitry Andric   do {                                                      \
143868d75effSDimitry Andric   } while (false)
143968d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
144068d75effSDimitry Andric   do {                                                \
144168d75effSDimitry Andric   } while (false)  // FIXME
144268d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
144368d75effSDimitry Andric   do {                                                         \
144468d75effSDimitry Andric   } while (false)  // FIXME
144568d75effSDimitry Andric #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
144668d75effSDimitry Andric #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
144768d75effSDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
144868d75effSDimitry Andric   do {                                                                         \
144968d75effSDimitry Andric     link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle));                   \
145068d75effSDimitry Andric     if (filename && map)                                                       \
145168d75effSDimitry Andric       ForEachMappedRegion(map, __msan_unpoison);                               \
145268d75effSDimitry Andric   } while (false)
145368d75effSDimitry Andric 
14545ffd83dbSDimitry Andric #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
14555ffd83dbSDimitry Andric 
145668d75effSDimitry Andric #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
145768d75effSDimitry Andric   if (MsanThread *t = GetCurrentThread()) {                                    \
145868d75effSDimitry Andric     *begin = t->tls_begin();                                                   \
145968d75effSDimitry Andric     *end = t->tls_end();                                                       \
146068d75effSDimitry Andric   } else {                                                                     \
146168d75effSDimitry Andric     *begin = *end = 0;                                                         \
146268d75effSDimitry Andric   }
146368d75effSDimitry Andric 
146468d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
146568d75effSDimitry Andric   {                                                         \
146668d75effSDimitry Andric     (void)ctx;                                              \
146768d75effSDimitry Andric     return __msan_memset(block, c, size);                   \
146868d75effSDimitry Andric   }
146968d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
147068d75effSDimitry Andric   {                                                          \
147168d75effSDimitry Andric     (void)ctx;                                               \
147268d75effSDimitry Andric     return __msan_memmove(to, from, size);                   \
147368d75effSDimitry Andric   }
147468d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
147568d75effSDimitry Andric   {                                                         \
147668d75effSDimitry Andric     (void)ctx;                                              \
147768d75effSDimitry Andric     return __msan_memcpy(to, from, size);                   \
147868d75effSDimitry Andric   }
147968d75effSDimitry Andric 
148068d75effSDimitry Andric #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
148168d75effSDimitry Andric   do {                                                      \
148268d75effSDimitry Andric     GET_STORE_STACK_TRACE;                                  \
148368d75effSDimitry Andric     CopyShadowAndOrigin(to, from, size, &stack);            \
148468d75effSDimitry Andric     __msan_unpoison(to + size, 1);                          \
148568d75effSDimitry Andric   } while (false)
148668d75effSDimitry Andric 
148768d75effSDimitry Andric #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
148868d75effSDimitry Andric                                      offset)                                   \
148968d75effSDimitry Andric   do {                                                                         \
149068d75effSDimitry Andric     return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off);       \
149168d75effSDimitry Andric   } while (false)
149268d75effSDimitry Andric 
149368d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform_interceptors.h"
149406c3fb27SDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
149568d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors.inc"
149668d75effSDimitry Andric 
149768d75effSDimitry Andric static uptr signal_impl(int signo, uptr cb);
149868d75effSDimitry Andric static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
149968d75effSDimitry Andric                           __sanitizer_sigaction *oldact);
150068d75effSDimitry Andric 
150168d75effSDimitry Andric #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
150268d75effSDimitry Andric   { return sigaction_impl(signo, act, oldact); }
150368d75effSDimitry Andric 
150468d75effSDimitry Andric #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
150568d75effSDimitry Andric   {                                                          \
150668d75effSDimitry Andric     handler = signal_impl(signo, handler);                   \
150768d75effSDimitry Andric     InterceptorScope interceptor_scope;                      \
150868d75effSDimitry Andric     return REAL(func)(signo, handler);                       \
150968d75effSDimitry Andric   }
151068d75effSDimitry Andric 
151106c3fb27SDimitry Andric #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
151206c3fb27SDimitry Andric 
151368d75effSDimitry Andric #include "sanitizer_common/sanitizer_signal_interceptors.inc"
151468d75effSDimitry Andric 
sigaction_impl(int signo,const __sanitizer_sigaction * act,__sanitizer_sigaction * oldact)151568d75effSDimitry Andric static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
151668d75effSDimitry Andric                           __sanitizer_sigaction *oldact) {
151768d75effSDimitry Andric   ENSURE_MSAN_INITED();
1518fe6060f1SDimitry Andric   if (signo <= 0 || signo >= kMaxSignals) {
1519fe6060f1SDimitry Andric     errno = errno_EINVAL;
1520fe6060f1SDimitry Andric     return -1;
1521fe6060f1SDimitry Andric   }
152268d75effSDimitry Andric   if (act) read_sigaction(act);
152368d75effSDimitry Andric   int res;
152468d75effSDimitry Andric   if (flags()->wrap_signals) {
152568d75effSDimitry Andric     SpinMutexLock lock(&sigactions_mu);
152668d75effSDimitry Andric     uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
152768d75effSDimitry Andric     __sanitizer_sigaction new_act;
152868d75effSDimitry Andric     __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
152968d75effSDimitry Andric     if (act) {
153068d75effSDimitry Andric       REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
153168d75effSDimitry Andric       uptr cb = (uptr)pnew_act->sigaction;
153268d75effSDimitry Andric       uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
153368d75effSDimitry Andric                         ? (uptr)SignalAction
153468d75effSDimitry Andric                         : (uptr)SignalHandler;
153568d75effSDimitry Andric       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
153668d75effSDimitry Andric         atomic_store(&sigactions[signo], cb, memory_order_relaxed);
153768d75effSDimitry Andric         pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb;
153868d75effSDimitry Andric       }
153968d75effSDimitry Andric     }
154068d75effSDimitry Andric     res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact);
154168d75effSDimitry Andric     if (res == 0 && oldact) {
154268d75effSDimitry Andric       uptr cb = (uptr)oldact->sigaction;
154368d75effSDimitry Andric       if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) {
154468d75effSDimitry Andric         oldact->sigaction = (decltype(oldact->sigaction))old_cb;
154568d75effSDimitry Andric       }
154668d75effSDimitry Andric     }
154768d75effSDimitry Andric   } else {
154868d75effSDimitry Andric     res = REAL(SIGACTION_SYMNAME)(signo, act, oldact);
154968d75effSDimitry Andric   }
155068d75effSDimitry Andric 
155168d75effSDimitry Andric   if (res == 0 && oldact) {
155268d75effSDimitry Andric     __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
155368d75effSDimitry Andric   }
155468d75effSDimitry Andric   return res;
155568d75effSDimitry Andric }
155668d75effSDimitry Andric 
signal_impl(int signo,uptr cb)155768d75effSDimitry Andric static uptr signal_impl(int signo, uptr cb) {
155868d75effSDimitry Andric   ENSURE_MSAN_INITED();
1559fe6060f1SDimitry Andric   if (signo <= 0 || signo >= kMaxSignals) {
1560fe6060f1SDimitry Andric     errno = errno_EINVAL;
1561fe6060f1SDimitry Andric     return -1;
1562fe6060f1SDimitry Andric   }
156368d75effSDimitry Andric   if (flags()->wrap_signals) {
156468d75effSDimitry Andric     SpinMutexLock lock(&sigactions_mu);
156568d75effSDimitry Andric     if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
156668d75effSDimitry Andric       atomic_store(&sigactions[signo], cb, memory_order_relaxed);
156768d75effSDimitry Andric       cb = (uptr)&SignalHandler;
156868d75effSDimitry Andric     }
156968d75effSDimitry Andric   }
157068d75effSDimitry Andric   return cb;
157168d75effSDimitry Andric }
157268d75effSDimitry Andric 
157368d75effSDimitry Andric #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
157468d75effSDimitry Andric #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
157568d75effSDimitry Andric   do {                                       \
157668d75effSDimitry Andric   } while (false)
157768d75effSDimitry Andric #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
157868d75effSDimitry Andric   do {                                       \
157968d75effSDimitry Andric   } while (false)
158068d75effSDimitry Andric #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
158168d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_syscalls.inc"
158268d75effSDimitry Andric #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
158368d75effSDimitry Andric 
INTERCEPTOR(const char *,strsignal,int sig)158481ad6265SDimitry Andric INTERCEPTOR(const char *, strsignal, int sig) {
158581ad6265SDimitry Andric   void *ctx;
158681ad6265SDimitry Andric   COMMON_INTERCEPTOR_ENTER(ctx, strsignal, sig);
158781ad6265SDimitry Andric   const char *res = REAL(strsignal)(sig);
158881ad6265SDimitry Andric   if (res)
158981ad6265SDimitry Andric     __msan_unpoison(res, internal_strlen(res) + 1);
159081ad6265SDimitry Andric   return res;
159181ad6265SDimitry Andric }
159281ad6265SDimitry Andric 
INTERCEPTOR(int,dladdr,void * addr,void * info)159306c3fb27SDimitry Andric INTERCEPTOR(int, dladdr, void *addr, void *info) {
159468d75effSDimitry Andric   void *ctx;
159568d75effSDimitry Andric   COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
159668d75effSDimitry Andric   int res = REAL(dladdr)(addr, info);
159706c3fb27SDimitry Andric   if (res != 0)
159806c3fb27SDimitry Andric     UnpoisonDllAddrInfo(info);
159906c3fb27SDimitry Andric   return res;
160006c3fb27SDimitry Andric }
160106c3fb27SDimitry Andric 
160206c3fb27SDimitry Andric #if SANITIZER_GLIBC
INTERCEPTOR(int,dladdr1,void * addr,void * info,void ** extra_info,int flags)160306c3fb27SDimitry Andric INTERCEPTOR(int, dladdr1, void *addr, void *info, void **extra_info,
160406c3fb27SDimitry Andric             int flags) {
160506c3fb27SDimitry Andric   void *ctx;
160606c3fb27SDimitry Andric   COMMON_INTERCEPTOR_ENTER(ctx, dladdr1, addr, info, extra_info, flags);
160706c3fb27SDimitry Andric   int res = REAL(dladdr1)(addr, info, extra_info, flags);
160868d75effSDimitry Andric   if (res != 0) {
160906c3fb27SDimitry Andric     UnpoisonDllAddrInfo(info);
161006c3fb27SDimitry Andric     UnpoisonDllAddr1ExtraInfo(extra_info, flags);
161168d75effSDimitry Andric   }
161268d75effSDimitry Andric   return res;
161368d75effSDimitry Andric }
161406c3fb27SDimitry Andric #  define MSAN_MAYBE_INTERCEPT_DLADDR1 MSAN_INTERCEPT_FUNC(dladdr1)
161506c3fb27SDimitry Andric #else
161606c3fb27SDimitry Andric #define MSAN_MAYBE_INTERCEPT_DLADDR1
161706c3fb27SDimitry Andric #endif
161868d75effSDimitry Andric 
INTERCEPTOR(char *,dlerror,int fake)161968d75effSDimitry Andric INTERCEPTOR(char *, dlerror, int fake) {
162068d75effSDimitry Andric   void *ctx;
162168d75effSDimitry Andric   COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
162268d75effSDimitry Andric   char *res = REAL(dlerror)(fake);
1623349cc55cSDimitry Andric   if (res)
1624349cc55cSDimitry Andric     __msan_unpoison(res, internal_strlen(res) + 1);
162568d75effSDimitry Andric   return res;
162668d75effSDimitry Andric }
162768d75effSDimitry Andric 
162868d75effSDimitry Andric typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
162968d75effSDimitry Andric                                   void *data);
163068d75effSDimitry Andric struct dl_iterate_phdr_data {
163168d75effSDimitry Andric   dl_iterate_phdr_cb callback;
163268d75effSDimitry Andric   void *data;
163368d75effSDimitry Andric };
163468d75effSDimitry Andric 
msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info * info,SIZE_T size,void * data)163568d75effSDimitry Andric static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
163668d75effSDimitry Andric                                    void *data) {
163768d75effSDimitry Andric   if (info) {
163868d75effSDimitry Andric     __msan_unpoison(info, size);
163968d75effSDimitry Andric     if (info->dlpi_phdr && info->dlpi_phnum)
164068d75effSDimitry Andric       __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
164168d75effSDimitry Andric     if (info->dlpi_name)
1642349cc55cSDimitry Andric       __msan_unpoison(info->dlpi_name, internal_strlen(info->dlpi_name) + 1);
164368d75effSDimitry Andric   }
164468d75effSDimitry Andric   dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
164568d75effSDimitry Andric   UnpoisonParam(3);
164668d75effSDimitry Andric   return cbdata->callback(info, size, cbdata->data);
164768d75effSDimitry Andric }
164868d75effSDimitry Andric 
INTERCEPTOR(void *,shmat,int shmid,const void * shmaddr,int shmflg)164968d75effSDimitry Andric INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
165068d75effSDimitry Andric   ENSURE_MSAN_INITED();
165168d75effSDimitry Andric   void *p = REAL(shmat)(shmid, shmaddr, shmflg);
165268d75effSDimitry Andric   if (p != (void *)-1) {
165368d75effSDimitry Andric     __sanitizer_shmid_ds ds;
165468d75effSDimitry Andric     int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
165568d75effSDimitry Andric     if (!res) {
165668d75effSDimitry Andric       __msan_unpoison(p, ds.shm_segsz);
165768d75effSDimitry Andric     }
165868d75effSDimitry Andric   }
165968d75effSDimitry Andric   return p;
166068d75effSDimitry Andric }
166168d75effSDimitry Andric 
INTERCEPTOR(int,dl_iterate_phdr,dl_iterate_phdr_cb callback,void * data)166268d75effSDimitry Andric INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
166368d75effSDimitry Andric   void *ctx;
166468d75effSDimitry Andric   COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
166568d75effSDimitry Andric   dl_iterate_phdr_data cbdata;
166668d75effSDimitry Andric   cbdata.callback = callback;
166768d75effSDimitry Andric   cbdata.data = data;
166868d75effSDimitry Andric   int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
166968d75effSDimitry Andric   return res;
167068d75effSDimitry Andric }
167168d75effSDimitry Andric 
167268d75effSDimitry Andric // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *,wcschr,void * s,wchar_t wc,void * ps)167368d75effSDimitry Andric INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
167468d75effSDimitry Andric   ENSURE_MSAN_INITED();
167568d75effSDimitry Andric   wchar_t *res = REAL(wcschr)(s, wc, ps);
167668d75effSDimitry Andric   return res;
167768d75effSDimitry Andric }
167868d75effSDimitry Andric 
167968d75effSDimitry Andric // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *,wcscpy,wchar_t * dest,const wchar_t * src)168068d75effSDimitry Andric INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
168168d75effSDimitry Andric   ENSURE_MSAN_INITED();
168268d75effSDimitry Andric   GET_STORE_STACK_TRACE;
168368d75effSDimitry Andric   wchar_t *res = REAL(wcscpy)(dest, src);
1684349cc55cSDimitry Andric   CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (internal_wcslen(src) + 1),
168568d75effSDimitry Andric                       &stack);
168668d75effSDimitry Andric   return res;
168768d75effSDimitry Andric }
168868d75effSDimitry Andric 
INTERCEPTOR(wchar_t *,wcsncpy,wchar_t * dest,const wchar_t * src,SIZE_T n)168968d75effSDimitry Andric INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
169068d75effSDimitry Andric   ENSURE_MSAN_INITED();
169168d75effSDimitry Andric   GET_STORE_STACK_TRACE;
1692349cc55cSDimitry Andric   SIZE_T copy_size = internal_wcsnlen(src, n);
169368d75effSDimitry Andric   if (copy_size < n) copy_size++;           // trailing \0
169468d75effSDimitry Andric   wchar_t *res = REAL(wcsncpy)(dest, src, n);
169568d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
169668d75effSDimitry Andric   __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
169768d75effSDimitry Andric   return res;
169868d75effSDimitry Andric }
169968d75effSDimitry Andric 
170068d75effSDimitry Andric // These interface functions reside here so that they can use
170168d75effSDimitry Andric // REAL(memset), etc.
__msan_unpoison(const void * a,uptr size)170268d75effSDimitry Andric void __msan_unpoison(const void *a, uptr size) {
170368d75effSDimitry Andric   if (!MEM_IS_APP(a)) return;
170468d75effSDimitry Andric   SetShadow(a, size, 0);
170568d75effSDimitry Andric }
170668d75effSDimitry Andric 
__msan_poison(const void * a,uptr size)170768d75effSDimitry Andric void __msan_poison(const void *a, uptr size) {
170868d75effSDimitry Andric   if (!MEM_IS_APP(a)) return;
170968d75effSDimitry Andric   SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
171068d75effSDimitry Andric }
171168d75effSDimitry Andric 
__msan_poison_stack(void * a,uptr size)171268d75effSDimitry Andric void __msan_poison_stack(void *a, uptr size) {
171368d75effSDimitry Andric   if (!MEM_IS_APP(a)) return;
171468d75effSDimitry Andric   SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
171568d75effSDimitry Andric }
171668d75effSDimitry Andric 
__msan_unpoison_param(uptr n)171768d75effSDimitry Andric void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }
171868d75effSDimitry Andric 
__msan_clear_and_unpoison(void * a,uptr size)171968d75effSDimitry Andric void __msan_clear_and_unpoison(void *a, uptr size) {
172068d75effSDimitry Andric   REAL(memset)(a, 0, size);
172168d75effSDimitry Andric   SetShadow(a, size, 0);
172268d75effSDimitry Andric }
172368d75effSDimitry Andric 
__msan_memcpy(void * dest,const void * src,SIZE_T n)172468d75effSDimitry Andric void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
172568d75effSDimitry Andric   if (!msan_inited) return internal_memcpy(dest, src, n);
172681ad6265SDimitry Andric   if (msan_init_is_running || __msan::IsInSymbolizerOrUnwider())
172768d75effSDimitry Andric     return REAL(memcpy)(dest, src, n);
172868d75effSDimitry Andric   ENSURE_MSAN_INITED();
172968d75effSDimitry Andric   GET_STORE_STACK_TRACE;
173068d75effSDimitry Andric   void *res = REAL(memcpy)(dest, src, n);
173168d75effSDimitry Andric   CopyShadowAndOrigin(dest, src, n, &stack);
173268d75effSDimitry Andric   return res;
173368d75effSDimitry Andric }
173468d75effSDimitry Andric 
__msan_memset(void * s,int c,SIZE_T n)173568d75effSDimitry Andric void *__msan_memset(void *s, int c, SIZE_T n) {
173668d75effSDimitry Andric   if (!msan_inited) return internal_memset(s, c, n);
173768d75effSDimitry Andric   if (msan_init_is_running) return REAL(memset)(s, c, n);
173868d75effSDimitry Andric   ENSURE_MSAN_INITED();
173968d75effSDimitry Andric   void *res = REAL(memset)(s, c, n);
174068d75effSDimitry Andric   __msan_unpoison(s, n);
174168d75effSDimitry Andric   return res;
174268d75effSDimitry Andric }
174368d75effSDimitry Andric 
__msan_memmove(void * dest,const void * src,SIZE_T n)174468d75effSDimitry Andric void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
174568d75effSDimitry Andric   if (!msan_inited) return internal_memmove(dest, src, n);
174668d75effSDimitry Andric   if (msan_init_is_running) return REAL(memmove)(dest, src, n);
174768d75effSDimitry Andric   ENSURE_MSAN_INITED();
174868d75effSDimitry Andric   GET_STORE_STACK_TRACE;
174968d75effSDimitry Andric   void *res = REAL(memmove)(dest, src, n);
175068d75effSDimitry Andric   MoveShadowAndOrigin(dest, src, n, &stack);
175168d75effSDimitry Andric   return res;
175268d75effSDimitry Andric }
175368d75effSDimitry Andric 
__msan_unpoison_string(const char * s)175468d75effSDimitry Andric void __msan_unpoison_string(const char* s) {
175568d75effSDimitry Andric   if (!MEM_IS_APP(s)) return;
1756349cc55cSDimitry Andric   __msan_unpoison(s, internal_strlen(s) + 1);
175768d75effSDimitry Andric }
175868d75effSDimitry Andric 
175968d75effSDimitry Andric namespace __msan {
176068d75effSDimitry Andric 
InitializeInterceptors()176168d75effSDimitry Andric void InitializeInterceptors() {
176268d75effSDimitry Andric   static int inited = 0;
176368d75effSDimitry Andric   CHECK_EQ(inited, 0);
176468d75effSDimitry Andric 
1765*0fca6ea1SDimitry Andric   __interception::DoesNotSupportStaticLinking();
1766*0fca6ea1SDimitry Andric 
176768d75effSDimitry Andric   new(interceptor_ctx()) InterceptorContext();
176868d75effSDimitry Andric 
176968d75effSDimitry Andric   InitializeCommonInterceptors();
177068d75effSDimitry Andric   InitializeSignalInterceptors();
177168d75effSDimitry Andric 
177268d75effSDimitry Andric   INTERCEPT_FUNCTION(posix_memalign);
177368d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MEMALIGN;
177468d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
177568d75effSDimitry Andric   INTERCEPT_FUNCTION(valloc);
177668d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_PVALLOC;
177768d75effSDimitry Andric   INTERCEPT_FUNCTION(malloc);
177868d75effSDimitry Andric   INTERCEPT_FUNCTION(calloc);
177968d75effSDimitry Andric   INTERCEPT_FUNCTION(realloc);
178068d75effSDimitry Andric   INTERCEPT_FUNCTION(reallocarray);
178168d75effSDimitry Andric   INTERCEPT_FUNCTION(free);
178268d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_CFREE;
178368d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
178468d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MALLINFO;
17855f757f3fSDimitry Andric   MSAN_MAYBE_INTERCEPT_MALLINFO2;
178668d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MALLOPT;
178768d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
178868d75effSDimitry Andric   INTERCEPT_FUNCTION(fread);
178968d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
179068d75effSDimitry Andric   INTERCEPT_FUNCTION(memccpy);
179168d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_MEMPCPY;
179268d75effSDimitry Andric   INTERCEPT_FUNCTION(bcopy);
179368d75effSDimitry Andric   INTERCEPT_FUNCTION(wmemset);
179468d75effSDimitry Andric   INTERCEPT_FUNCTION(wmemcpy);
179568d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_WMEMPCPY;
179668d75effSDimitry Andric   INTERCEPT_FUNCTION(wmemmove);
179768d75effSDimitry Andric   INTERCEPT_FUNCTION(strcpy);
179868d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_STPCPY;
1799bdd1243dSDimitry Andric   MSAN_MAYBE_INTERCEPT_STPNCPY;
180068d75effSDimitry Andric   INTERCEPT_FUNCTION(strdup);
180168d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___STRDUP;
180268d75effSDimitry Andric   INTERCEPT_FUNCTION(strncpy);
180368d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_GCVT;
180468d75effSDimitry Andric   INTERCEPT_FUNCTION(strcat);
180568d75effSDimitry Andric   INTERCEPT_FUNCTION(strncat);
180668d75effSDimitry Andric   INTERCEPT_STRTO(strtod);
180768d75effSDimitry Andric   INTERCEPT_STRTO(strtof);
18085f757f3fSDimitry Andric #ifdef SANITIZER_NLDBL_VERSION
18095f757f3fSDimitry Andric   INTERCEPT_STRTO_VER(strtold, SANITIZER_NLDBL_VERSION);
18105f757f3fSDimitry Andric #else
181168d75effSDimitry Andric   INTERCEPT_STRTO(strtold);
18125f757f3fSDimitry Andric #endif
181368d75effSDimitry Andric   INTERCEPT_STRTO(strtol);
181468d75effSDimitry Andric   INTERCEPT_STRTO(strtoul);
181568d75effSDimitry Andric   INTERCEPT_STRTO(strtoll);
181668d75effSDimitry Andric   INTERCEPT_STRTO(strtoull);
181768d75effSDimitry Andric   INTERCEPT_STRTO(strtouq);
181868d75effSDimitry Andric   INTERCEPT_STRTO(wcstod);
181968d75effSDimitry Andric   INTERCEPT_STRTO(wcstof);
18205f757f3fSDimitry Andric #ifdef SANITIZER_NLDBL_VERSION
18215f757f3fSDimitry Andric   INTERCEPT_STRTO_VER(wcstold, SANITIZER_NLDBL_VERSION);
18225f757f3fSDimitry Andric #else
182368d75effSDimitry Andric   INTERCEPT_STRTO(wcstold);
18245f757f3fSDimitry Andric #endif
182568d75effSDimitry Andric   INTERCEPT_STRTO(wcstol);
182668d75effSDimitry Andric   INTERCEPT_STRTO(wcstoul);
182768d75effSDimitry Andric   INTERCEPT_STRTO(wcstoll);
182868d75effSDimitry Andric   INTERCEPT_STRTO(wcstoull);
18298a4dda33SDimitry Andric #if SANITIZER_GLIBC
18308a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtod);
18318a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtof);
18328a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtold);
18338a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtol);
18348a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtoul);
18358a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtoll);
18368a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtoull);
18378a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_strtouq);
18388a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstod);
18398a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstof);
18408a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstold);
18418a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstol);
18428a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstoul);
18438a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstoll);
18448a4dda33SDimitry Andric   INTERCEPT_STRTO(__isoc23_wcstoull);
18458a4dda33SDimitry Andric #endif
18468a4dda33SDimitry Andric 
184768d75effSDimitry Andric #ifdef SANITIZER_NLDBL_VERSION
184868d75effSDimitry Andric   INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
184968d75effSDimitry Andric   INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
185068d75effSDimitry Andric #else
185168d75effSDimitry Andric   INTERCEPT_FUNCTION(vswprintf);
185268d75effSDimitry Andric   INTERCEPT_FUNCTION(swprintf);
185368d75effSDimitry Andric #endif
185468d75effSDimitry Andric   INTERCEPT_FUNCTION(strftime);
185568d75effSDimitry Andric   INTERCEPT_FUNCTION(strftime_l);
185668d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___STRFTIME_L;
185768d75effSDimitry Andric   INTERCEPT_FUNCTION(wcsftime);
185868d75effSDimitry Andric   INTERCEPT_FUNCTION(wcsftime_l);
185968d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
186068d75effSDimitry Andric   INTERCEPT_FUNCTION(mbtowc);
186168d75effSDimitry Andric   INTERCEPT_FUNCTION(mbrtowc);
186268d75effSDimitry Andric   INTERCEPT_FUNCTION(wcslen);
186368d75effSDimitry Andric   INTERCEPT_FUNCTION(wcsnlen);
186468d75effSDimitry Andric   INTERCEPT_FUNCTION(wcschr);
186568d75effSDimitry Andric   INTERCEPT_FUNCTION(wcscpy);
186668d75effSDimitry Andric   INTERCEPT_FUNCTION(wcsncpy);
186768d75effSDimitry Andric   INTERCEPT_FUNCTION(wcscmp);
186868d75effSDimitry Andric   INTERCEPT_FUNCTION(getenv);
186968d75effSDimitry Andric   INTERCEPT_FUNCTION(setenv);
187068d75effSDimitry Andric   INTERCEPT_FUNCTION(putenv);
187168d75effSDimitry Andric   INTERCEPT_FUNCTION(gettimeofday);
187268d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_FCVT;
187368d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_FSTAT;
187481ad6265SDimitry Andric   MSAN_MAYBE_INTERCEPT_FSTAT64;
187568d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___FXSTAT;
1876349cc55cSDimitry Andric   MSAN_MAYBE_INTERCEPT_FSTATAT;
187781ad6265SDimitry Andric   MSAN_MAYBE_INTERCEPT_FSTATAT64;
1878349cc55cSDimitry Andric   MSAN_MAYBE_INTERCEPT___FXSTATAT;
187968d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___FXSTAT64;
188068d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___FXSTATAT64;
188168d75effSDimitry Andric   INTERCEPT_FUNCTION(pipe);
188268d75effSDimitry Andric   INTERCEPT_FUNCTION(pipe2);
188368d75effSDimitry Andric   INTERCEPT_FUNCTION(socketpair);
188468d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
188568d75effSDimitry Andric   INTERCEPT_FUNCTION(getrlimit);
188668d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT___GETRLIMIT;
188768d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
188868d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_PRLIMIT;
188968d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_PRLIMIT64;
189068d75effSDimitry Andric   INTERCEPT_FUNCTION(gethostname);
189168d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
189268d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
189381ad6265SDimitry Andric   INTERCEPT_FUNCTION(strsignal);
189468d75effSDimitry Andric   INTERCEPT_FUNCTION(dladdr);
189506c3fb27SDimitry Andric   MSAN_MAYBE_INTERCEPT_DLADDR1;
189668d75effSDimitry Andric   INTERCEPT_FUNCTION(dlerror);
189768d75effSDimitry Andric   INTERCEPT_FUNCTION(dl_iterate_phdr);
189868d75effSDimitry Andric   INTERCEPT_FUNCTION(getrusage);
189968d75effSDimitry Andric #if defined(__mips__)
190068d75effSDimitry Andric   INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
190168d75effSDimitry Andric #else
190268d75effSDimitry Andric   INTERCEPT_FUNCTION(pthread_create);
190368d75effSDimitry Andric #endif
19040eae32dcSDimitry Andric   INTERCEPT_FUNCTION(pthread_join);
190568d75effSDimitry Andric   INTERCEPT_FUNCTION(pthread_key_create);
190606c3fb27SDimitry Andric #if SANITIZER_GLIBC
190706c3fb27SDimitry Andric   INTERCEPT_FUNCTION(pthread_tryjoin_np);
190806c3fb27SDimitry Andric   INTERCEPT_FUNCTION(pthread_timedjoin_np);
190906c3fb27SDimitry Andric #endif
191068d75effSDimitry Andric 
191168d75effSDimitry Andric #if SANITIZER_NETBSD
191268d75effSDimitry Andric   INTERCEPT_FUNCTION(__libc_thr_keycreate);
191368d75effSDimitry Andric #endif
191468d75effSDimitry Andric 
191568d75effSDimitry Andric   INTERCEPT_FUNCTION(pthread_join);
191668d75effSDimitry Andric   INTERCEPT_FUNCTION(tzset);
191768d75effSDimitry Andric   INTERCEPT_FUNCTION(atexit);
191868d75effSDimitry Andric   INTERCEPT_FUNCTION(__cxa_atexit);
191968d75effSDimitry Andric   INTERCEPT_FUNCTION(shmat);
192068d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_OPENPTY;
192168d75effSDimitry Andric   MSAN_MAYBE_INTERCEPT_FORKPTY;
192268d75effSDimitry Andric 
192368d75effSDimitry Andric   inited = 1;
192468d75effSDimitry Andric }
192568d75effSDimitry Andric } // namespace __msan
1926