1 //===-- msan_interceptors.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of MemorySanitizer.
11 // Interceptors for standard library functions.
13 // FIXME: move as many interceptors as possible into
14 // sanitizer_common/sanitizer_common_interceptors.h
15 //===----------------------------------------------------------------------===//
17 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
19 #include "interception/interception.h"
21 #include "msan_chained_origin_depot.h"
23 #include "msan_origin.h"
24 #include "msan_poisoning.h"
25 #include "msan_report.h"
26 #include "msan_thread.h"
27 #include "sanitizer_common/sanitizer_allocator.h"
28 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
29 #include "sanitizer_common/sanitizer_allocator_interface.h"
30 #include "sanitizer_common/sanitizer_atomic.h"
31 #include "sanitizer_common/sanitizer_common.h"
32 #include "sanitizer_common/sanitizer_errno.h"
33 #include "sanitizer_common/sanitizer_errno_codes.h"
34 #include "sanitizer_common/sanitizer_glibc_version.h"
35 #include "sanitizer_common/sanitizer_libc.h"
36 #include "sanitizer_common/sanitizer_linux.h"
37 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
38 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
39 #include "sanitizer_common/sanitizer_stackdepot.h"
40 #include "sanitizer_common/sanitizer_tls_get_addr.h"
41 #include "sanitizer_common/sanitizer_vector.h"
44 #define fstat __fstat50
45 #define gettimeofday __gettimeofday50
46 #define getrusage __getrusage50
47 #define tzset __tzset50
51 // ACHTUNG! No other system header includes in this file.
52 // Ideally, we should get rid of stdarg.h as well.
54 using namespace __msan
;
56 using __sanitizer::memory_order
;
57 using __sanitizer::atomic_load
;
58 using __sanitizer::atomic_store
;
59 using __sanitizer::atomic_uintptr_t
;
61 DECLARE_REAL(SIZE_T
, strlen
, const char *s
)
62 DECLARE_REAL(SIZE_T
, strnlen
, const char *s
, SIZE_T maxlen
)
63 DECLARE_REAL(void *, memcpy
, void *dest
, const void *src
, uptr n
)
64 DECLARE_REAL(void *, memset
, void *dest
, int c
, uptr n
)
66 // True if this is a nested interceptor.
67 static THREADLOCAL
int in_interceptor_scope
;
69 void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope
; }
70 void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope
; }
72 struct InterceptorScope
{
73 InterceptorScope() { ++in_interceptor_scope
; }
74 ~InterceptorScope() { --in_interceptor_scope
; }
77 bool IsInInterceptorScope() {
78 return in_interceptor_scope
;
81 struct DlsymAlloc
: public DlSymAllocator
<DlsymAlloc
> {
82 static bool UseImpl() { return !msan_inited
; }
85 #define ENSURE_MSAN_INITED() do { \
86 CHECK(!msan_init_is_running); \
92 // Check that [x, x+n) range is unpoisoned.
93 #define CHECK_UNPOISONED_0(x, n) \
95 sptr __offset = __msan_test_shadow(x, n); \
96 if (__msan::IsInSymbolizerOrUnwider()) \
98 if (__offset >= 0 && __msan::flags()->report_umrs) { \
100 ReportUMRInsideAddressRange(__func__, x, n, __offset); \
101 __msan::PrintWarningWithOrigin( \
102 pc, bp, __msan_get_origin((const char *)x + __offset)); \
103 if (__msan::flags()->halt_on_error) { \
104 Printf("Exiting\n"); \
110 // Check that [x, x+n) range is unpoisoned unless we are in a nested
112 #define CHECK_UNPOISONED(x, n) \
114 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
117 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
118 CHECK_UNPOISONED((x), \
119 common_flags()->strict_string_checks ? (len) + 1 : (n) )
121 #define CHECK_UNPOISONED_STRING(x, n) \
122 CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
124 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
125 INTERCEPTOR(SIZE_T
, fread_unlocked
, void *ptr
, SIZE_T size
, SIZE_T nmemb
,
127 ENSURE_MSAN_INITED();
128 SIZE_T res
= REAL(fread_unlocked
)(ptr
, size
, nmemb
, file
);
130 __msan_unpoison(ptr
, res
*size
);
133 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
135 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
138 #if !SANITIZER_NETBSD
139 INTERCEPTOR(void *, mempcpy
, void *dest
, const void *src
, SIZE_T n
) {
140 return (char *)__msan_memcpy(dest
, src
, n
) + n
;
142 #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
144 #define MSAN_MAYBE_INTERCEPT_MEMPCPY
147 INTERCEPTOR(void *, memccpy
, void *dest
, const void *src
, int c
, SIZE_T n
) {
148 ENSURE_MSAN_INITED();
149 void *res
= REAL(memccpy
)(dest
, src
, c
, n
);
150 CHECK(!res
|| (res
>= dest
&& res
<= (char *)dest
+ n
));
151 SIZE_T sz
= res
? (char *)res
- (char *)dest
: n
;
152 CHECK_UNPOISONED(src
, sz
);
153 __msan_unpoison(dest
, sz
);
157 INTERCEPTOR(void *, bcopy
, const void *src
, void *dest
, SIZE_T n
) {
158 return __msan_memmove(dest
, src
, n
);
161 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
162 GET_MALLOC_STACK_TRACE
;
164 int res
= msan_posix_memalign(memptr
, alignment
, size
, &stack
);
166 __msan_unpoison(memptr
, sizeof(*memptr
));
170 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
171 INTERCEPTOR(void *, memalign
, SIZE_T alignment
, SIZE_T size
) {
172 GET_MALLOC_STACK_TRACE
;
173 return msan_memalign(alignment
, size
, &stack
);
175 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
177 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
180 INTERCEPTOR(void *, aligned_alloc
, SIZE_T alignment
, SIZE_T size
) {
181 GET_MALLOC_STACK_TRACE
;
182 return msan_aligned_alloc(alignment
, size
, &stack
);
185 #if !SANITIZER_NETBSD
186 INTERCEPTOR(void *, __libc_memalign
, SIZE_T alignment
, SIZE_T size
) {
187 GET_MALLOC_STACK_TRACE
;
188 void *ptr
= msan_memalign(alignment
, size
, &stack
);
190 DTLS_on_libc_memalign(ptr
, size
);
193 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
195 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
198 INTERCEPTOR(void *, valloc
, SIZE_T size
) {
199 GET_MALLOC_STACK_TRACE
;
200 return msan_valloc(size
, &stack
);
203 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
204 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
205 GET_MALLOC_STACK_TRACE
;
206 return msan_pvalloc(size
, &stack
);
208 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
210 #define MSAN_MAYBE_INTERCEPT_PVALLOC
213 INTERCEPTOR(void, free
, void *ptr
) {
216 if (DlsymAlloc::PointerIsMine(ptr
))
217 return DlsymAlloc::Free(ptr
);
218 GET_MALLOC_STACK_TRACE
;
219 MsanDeallocate(&stack
, ptr
);
222 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
223 INTERCEPTOR(void, cfree
, void *ptr
) {
226 if (DlsymAlloc::PointerIsMine(ptr
))
227 return DlsymAlloc::Free(ptr
);
228 GET_MALLOC_STACK_TRACE
;
229 MsanDeallocate(&stack
, ptr
);
231 # define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
233 #define MSAN_MAYBE_INTERCEPT_CFREE
236 #if !SANITIZER_NETBSD
237 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
238 return __sanitizer_get_allocated_size(ptr
);
240 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
241 INTERCEPT_FUNCTION(malloc_usable_size)
243 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
246 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
247 // This function actually returns a struct by value, but we can't unpoison a
248 // temporary! The following is equivalent on all supported platforms but
249 // aarch64 (which uses a different register for sret value). We have a test
251 INTERCEPTOR(void, mallinfo
, __sanitizer_struct_mallinfo
*sret
) {
254 asm volatile("mov %0,x8" : "=r" (r8
));
255 sret
= reinterpret_cast<__sanitizer_struct_mallinfo
*>(r8
);
257 REAL(memset
)(sret
, 0, sizeof(*sret
));
258 __msan_unpoison(sret
, sizeof(*sret
));
260 #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
262 #define MSAN_MAYBE_INTERCEPT_MALLINFO
265 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
266 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
269 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
271 #define MSAN_MAYBE_INTERCEPT_MALLOPT
274 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
275 INTERCEPTOR(void, malloc_stats
, void) {
276 // FIXME: implement, but don't call REAL(malloc_stats)!
278 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
280 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
283 INTERCEPTOR(char *, strcpy
, char *dest
, const char *src
) {
284 ENSURE_MSAN_INITED();
285 GET_STORE_STACK_TRACE
;
286 SIZE_T n
= internal_strlen(src
);
287 CHECK_UNPOISONED_STRING(src
+ n
, 0);
288 char *res
= REAL(strcpy
)(dest
, src
);
289 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
293 INTERCEPTOR(char *, strncpy
, char *dest
, const char *src
, SIZE_T n
) {
294 ENSURE_MSAN_INITED();
295 GET_STORE_STACK_TRACE
;
296 SIZE_T copy_size
= internal_strnlen(src
, n
);
298 copy_size
++; // trailing \0
299 char *res
= REAL(strncpy
)(dest
, src
, n
);
300 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
301 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
305 #if !SANITIZER_NETBSD
306 INTERCEPTOR(char *, stpcpy
, char *dest
, const char *src
) {
307 ENSURE_MSAN_INITED();
308 GET_STORE_STACK_TRACE
;
309 SIZE_T n
= internal_strlen(src
);
310 CHECK_UNPOISONED_STRING(src
+ n
, 0);
311 char *res
= REAL(stpcpy
)(dest
, src
);
312 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
316 INTERCEPTOR(char *, stpncpy
, char *dest
, const char *src
, SIZE_T n
) {
317 ENSURE_MSAN_INITED();
318 GET_STORE_STACK_TRACE
;
319 SIZE_T copy_size
= Min(n
, internal_strnlen(src
, n
) + 1);
320 char *res
= REAL(stpncpy
)(dest
, src
, n
);
321 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
322 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
325 # define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
326 # define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
328 #define MSAN_MAYBE_INTERCEPT_STPCPY
329 # define MSAN_MAYBE_INTERCEPT_STPNCPY
332 INTERCEPTOR(char *, strdup
, char *src
) {
333 ENSURE_MSAN_INITED();
334 GET_STORE_STACK_TRACE
;
335 // On FreeBSD strdup() leverages strlen().
336 InterceptorScope interceptor_scope
;
337 SIZE_T n
= internal_strlen(src
);
338 CHECK_UNPOISONED_STRING(src
+ n
, 0);
339 char *res
= REAL(strdup
)(src
);
340 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
344 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
345 INTERCEPTOR(char *, __strdup
, char *src
) {
346 ENSURE_MSAN_INITED();
347 GET_STORE_STACK_TRACE
;
348 SIZE_T n
= internal_strlen(src
);
349 CHECK_UNPOISONED_STRING(src
+ n
, 0);
350 char *res
= REAL(__strdup
)(src
);
351 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
354 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
356 #define MSAN_MAYBE_INTERCEPT___STRDUP
359 #if !SANITIZER_NETBSD
360 INTERCEPTOR(char *, gcvt
, double number
, SIZE_T ndigit
, char *buf
) {
361 ENSURE_MSAN_INITED();
362 char *res
= REAL(gcvt
)(number
, ndigit
, buf
);
363 SIZE_T n
= internal_strlen(buf
);
364 __msan_unpoison(buf
, n
+ 1);
367 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
369 #define MSAN_MAYBE_INTERCEPT_GCVT
372 INTERCEPTOR(char *, strcat
, char *dest
, const char *src
) {
373 ENSURE_MSAN_INITED();
374 GET_STORE_STACK_TRACE
;
375 SIZE_T src_size
= internal_strlen(src
);
376 SIZE_T dest_size
= internal_strlen(dest
);
377 CHECK_UNPOISONED_STRING(src
+ src_size
, 0);
378 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
379 char *res
= REAL(strcat
)(dest
, src
);
380 CopyShadowAndOrigin(dest
+ dest_size
, src
, src_size
+ 1, &stack
);
384 INTERCEPTOR(char *, strncat
, char *dest
, const char *src
, SIZE_T n
) {
385 ENSURE_MSAN_INITED();
386 GET_STORE_STACK_TRACE
;
387 SIZE_T dest_size
= internal_strlen(dest
);
388 SIZE_T copy_size
= internal_strnlen(src
, n
);
389 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
390 char *res
= REAL(strncat
)(dest
, src
, n
);
391 CopyShadowAndOrigin(dest
+ dest_size
, src
, copy_size
, &stack
);
392 __msan_unpoison(dest
+ dest_size
+ copy_size
, 1); // \0
396 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
397 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
398 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
399 ENSURE_MSAN_INITED(); \
400 ret_type res = REAL(func)(__VA_ARGS__); \
401 __msan_unpoison(endptr, sizeof(*endptr)); \
404 // On s390x, long double return values are passed via implicit reference,
405 // which needs to be unpoisoned. We make the implicit pointer explicit.
406 #define INTERCEPTOR_STRTO_SRET_BODY(func, sret, ...) \
407 ENSURE_MSAN_INITED(); \
408 REAL(func)(sret, __VA_ARGS__); \
409 __msan_unpoison(sret, sizeof(*sret)); \
410 __msan_unpoison(endptr, sizeof(*endptr));
412 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
413 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
414 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
417 #define INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
418 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
419 char_type **endptr) { \
420 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr); \
423 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
424 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
426 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
429 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
430 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
432 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
435 #define INTERCEPTOR_STRTO_SRET_LOC(ret_type, func, char_type) \
436 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
437 char_type **endptr, void *loc) { \
438 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr, loc); \
441 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
442 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
443 int base, void *loc) { \
444 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
448 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
449 INTERCEPTOR_STRTO(ret_type, func, char_type) \
450 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
452 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
453 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
454 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type)
456 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
457 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
458 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
461 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
462 INTERCEPTOR_STRTO(ret_type, func, char_type) \
463 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
464 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
465 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
467 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
468 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
469 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type) \
470 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_l, char_type) \
471 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_internal, char_type)
473 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
474 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
475 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
476 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
477 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
480 INTERCEPTORS_STRTO(double, strtod
, char)
481 INTERCEPTORS_STRTO(float, strtof
, char)
483 INTERCEPTORS_STRTO_SRET(long double, strtold
, char)
485 INTERCEPTORS_STRTO(long double, strtold
, char)
487 INTERCEPTORS_STRTO_BASE(long, strtol
, char)
488 INTERCEPTORS_STRTO_BASE(long long, strtoll
, char)
489 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul
, char)
490 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull
, char)
491 INTERCEPTORS_STRTO_BASE(u64
, strtouq
, char)
493 INTERCEPTORS_STRTO(double, wcstod
, wchar_t)
494 INTERCEPTORS_STRTO(float, wcstof
, wchar_t)
496 INTERCEPTORS_STRTO_SRET(long double, wcstold
, wchar_t)
498 INTERCEPTORS_STRTO(long double, wcstold
, wchar_t)
500 INTERCEPTORS_STRTO_BASE(long, wcstol
, wchar_t)
501 INTERCEPTORS_STRTO_BASE(long long, wcstoll
, wchar_t)
502 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul
, wchar_t)
503 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull
, wchar_t)
506 INTERCEPTORS_STRTO(double, __isoc23_strtod
, char)
507 INTERCEPTORS_STRTO(float, __isoc23_strtof
, char)
509 INTERCEPTORS_STRTO_SRET(long double, __isoc23_strtold
, char)
511 INTERCEPTORS_STRTO(long double, __isoc23_strtold
, char)
513 INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol
, char)
514 INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll
, char)
515 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul
, char)
516 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull
, char)
517 INTERCEPTORS_STRTO_BASE(u64
, __isoc23_strtouq
, char)
519 INTERCEPTORS_STRTO(double, __isoc23_wcstod
, wchar_t)
520 INTERCEPTORS_STRTO(float, __isoc23_wcstof
, wchar_t)
522 INTERCEPTORS_STRTO_SRET(long double, __isoc23_wcstold
, wchar_t)
524 INTERCEPTORS_STRTO(long double, __isoc23_wcstold
, wchar_t)
526 INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol
, wchar_t)
527 INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll
, wchar_t)
528 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul
, wchar_t)
529 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull
, wchar_t)
533 #define INTERCEPT_STRTO(func) \
534 INTERCEPT_FUNCTION(func); \
535 INTERCEPT_FUNCTION(func##_l);
537 #define INTERCEPT_STRTO(func) \
538 INTERCEPT_FUNCTION(func); \
539 INTERCEPT_FUNCTION(func##_l); \
540 INTERCEPT_FUNCTION(__##func##_l); \
541 INTERCEPT_FUNCTION(__##func##_internal);
543 #define INTERCEPT_STRTO_VER(func, ver) \
544 INTERCEPT_FUNCTION_VER(func, ver); \
545 INTERCEPT_FUNCTION_VER(func##_l, ver); \
546 INTERCEPT_FUNCTION_VER(__##func##_l, ver); \
547 INTERCEPT_FUNCTION_VER(__##func##_internal, ver);
551 // FIXME: support *wprintf in common format interceptors.
552 INTERCEPTOR(int, vswprintf
, void *str
, uptr size
, void *format
, va_list ap
) {
553 ENSURE_MSAN_INITED();
554 int res
= REAL(vswprintf
)(str
, size
, format
, ap
);
556 __msan_unpoison(str
, 4 * (res
+ 1));
561 INTERCEPTOR(int, swprintf
, void *str
, uptr size
, void *format
, ...) {
562 ENSURE_MSAN_INITED();
564 va_start(ap
, format
);
565 int res
= vswprintf(str
, size
, format
, ap
);
570 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
571 ENSURE_MSAN_INITED(); \
572 InterceptorScope interceptor_scope; \
573 ret_type res = REAL(func)(s, __VA_ARGS__); \
574 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
577 INTERCEPTOR(SIZE_T
, strftime
, char *s
, SIZE_T max
, const char *format
,
578 __sanitizer_tm
*tm
) {
579 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime
, s
, max
, format
, tm
);
582 INTERCEPTOR(SIZE_T
, strftime_l
, char *s
, SIZE_T max
, const char *format
,
583 __sanitizer_tm
*tm
, void *loc
) {
584 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime_l
, s
, max
, format
, tm
, loc
);
587 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
588 INTERCEPTOR(SIZE_T
, __strftime_l
, char *s
, SIZE_T max
, const char *format
,
589 __sanitizer_tm
*tm
, void *loc
) {
590 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, __strftime_l
, s
, max
, format
, tm
,
593 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
595 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
598 INTERCEPTOR(SIZE_T
, wcsftime
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
599 __sanitizer_tm
*tm
) {
600 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime
, s
, max
, format
, tm
);
603 INTERCEPTOR(SIZE_T
, wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
604 __sanitizer_tm
*tm
, void *loc
) {
605 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime_l
, s
, max
, format
, tm
,
609 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
610 INTERCEPTOR(SIZE_T
, __wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
611 __sanitizer_tm
*tm
, void *loc
) {
612 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, __wcsftime_l
, s
, max
, format
, tm
,
615 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
617 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
620 INTERCEPTOR(int, mbtowc
, wchar_t *dest
, const char *src
, SIZE_T n
) {
621 ENSURE_MSAN_INITED();
622 int res
= REAL(mbtowc
)(dest
, src
, n
);
623 if (res
!= -1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
627 INTERCEPTOR(SIZE_T
, mbrtowc
, wchar_t *dest
, const char *src
, SIZE_T n
,
629 ENSURE_MSAN_INITED();
630 SIZE_T res
= REAL(mbrtowc
)(dest
, src
, n
, ps
);
631 if (res
!= (SIZE_T
)-1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
635 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
636 INTERCEPTOR(wchar_t *, wmemcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
637 ENSURE_MSAN_INITED();
638 GET_STORE_STACK_TRACE
;
639 wchar_t *res
= REAL(wmemcpy
)(dest
, src
, n
);
640 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
644 #if !SANITIZER_NETBSD
645 INTERCEPTOR(wchar_t *, wmempcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
646 ENSURE_MSAN_INITED();
647 GET_STORE_STACK_TRACE
;
648 wchar_t *res
= REAL(wmempcpy
)(dest
, src
, n
);
649 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
652 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
654 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
657 INTERCEPTOR(wchar_t *, wmemset
, wchar_t *s
, wchar_t c
, SIZE_T n
) {
658 CHECK(MEM_IS_APP(s
));
659 ENSURE_MSAN_INITED();
660 wchar_t *res
= REAL(wmemset
)(s
, c
, n
);
661 __msan_unpoison(s
, n
* sizeof(wchar_t));
665 INTERCEPTOR(wchar_t *, wmemmove
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
666 ENSURE_MSAN_INITED();
667 GET_STORE_STACK_TRACE
;
668 wchar_t *res
= REAL(wmemmove
)(dest
, src
, n
);
669 MoveShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
673 INTERCEPTOR(int, wcscmp
, const wchar_t *s1
, const wchar_t *s2
) {
674 ENSURE_MSAN_INITED();
675 int res
= REAL(wcscmp
)(s1
, s2
);
679 INTERCEPTOR(int, gettimeofday
, void *tv
, void *tz
) {
680 ENSURE_MSAN_INITED();
681 int res
= REAL(gettimeofday
)(tv
, tz
);
683 __msan_unpoison(tv
, 16);
685 __msan_unpoison(tz
, 8);
689 #if !SANITIZER_NETBSD
690 INTERCEPTOR(char *, fcvt
, double x
, int a
, int *b
, int *c
) {
691 ENSURE_MSAN_INITED();
692 char *res
= REAL(fcvt
)(x
, a
, b
, c
);
693 __msan_unpoison(b
, sizeof(*b
));
694 __msan_unpoison(c
, sizeof(*c
));
696 __msan_unpoison(res
, internal_strlen(res
) + 1);
699 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
701 #define MSAN_MAYBE_INTERCEPT_FCVT
704 INTERCEPTOR(char *, getenv
, char *name
) {
705 if (msan_init_is_running
)
706 return REAL(getenv
)(name
);
707 ENSURE_MSAN_INITED();
708 char *res
= REAL(getenv
)(name
);
710 __msan_unpoison(res
, internal_strlen(res
) + 1);
714 extern char **environ
;
716 static void UnpoisonEnviron() {
717 char **envp
= environ
;
718 for (; *envp
; ++envp
) {
719 __msan_unpoison(envp
, sizeof(*envp
));
720 __msan_unpoison(*envp
, internal_strlen(*envp
) + 1);
722 // Trailing NULL pointer.
723 __msan_unpoison(envp
, sizeof(*envp
));
726 INTERCEPTOR(int, setenv
, const char *name
, const char *value
, int overwrite
) {
727 ENSURE_MSAN_INITED();
728 CHECK_UNPOISONED_STRING(name
, 0);
729 int res
= REAL(setenv
)(name
, value
, overwrite
);
730 if (!res
) UnpoisonEnviron();
734 INTERCEPTOR(int, putenv
, char *string
) {
735 ENSURE_MSAN_INITED();
736 int res
= REAL(putenv
)(string
);
737 if (!res
) UnpoisonEnviron();
741 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
742 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
743 INTERCEPTOR(int, fstat
, int fd
, void *buf
) {
744 ENSURE_MSAN_INITED();
745 int res
= REAL(fstat
)(fd
, buf
);
747 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
750 # define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
752 #define MSAN_MAYBE_INTERCEPT_FSTAT
755 #if SANITIZER_STAT_LINUX
756 INTERCEPTOR(int, fstat64
, int fd
, void *buf
) {
757 ENSURE_MSAN_INITED();
758 int res
= REAL(fstat64
)(fd
, buf
);
760 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
763 # define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
765 # define MSAN_MAYBE_INTERCEPT_FSTAT64
769 INTERCEPTOR(int, __fxstat
, int magic
, int fd
, void *buf
) {
770 ENSURE_MSAN_INITED();
771 int res
= REAL(__fxstat
)(magic
, fd
, buf
);
773 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
776 # define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
778 #define MSAN_MAYBE_INTERCEPT___FXSTAT
782 INTERCEPTOR(int, __fxstat64
, int magic
, int fd
, void *buf
) {
783 ENSURE_MSAN_INITED();
784 int res
= REAL(__fxstat64
)(magic
, fd
, buf
);
786 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
789 # define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
791 # define MSAN_MAYBE_INTERCEPT___FXSTAT64
794 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
795 INTERCEPTOR(int, fstatat
, int fd
, char *pathname
, void *buf
, int flags
) {
796 ENSURE_MSAN_INITED();
797 int res
= REAL(fstatat
)(fd
, pathname
, buf
, flags
);
798 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
801 # define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
803 # define MSAN_MAYBE_INTERCEPT_FSTATAT
806 #if SANITIZER_STAT_LINUX
807 INTERCEPTOR(int, fstatat64
, int fd
, char *pathname
, void *buf
, int flags
) {
808 ENSURE_MSAN_INITED();
809 int res
= REAL(fstatat64
)(fd
, pathname
, buf
, flags
);
811 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
814 # define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
816 # define MSAN_MAYBE_INTERCEPT_FSTATAT64
820 INTERCEPTOR(int, __fxstatat
, int magic
, int fd
, char *pathname
, void *buf
,
822 ENSURE_MSAN_INITED();
823 int res
= REAL(__fxstatat
)(magic
, fd
, pathname
, buf
, flags
);
824 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
827 # define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
829 # define MSAN_MAYBE_INTERCEPT___FXSTATAT
833 INTERCEPTOR(int, __fxstatat64
, int magic
, int fd
, char *pathname
, void *buf
,
835 ENSURE_MSAN_INITED();
836 int res
= REAL(__fxstatat64
)(magic
, fd
, pathname
, buf
, flags
);
837 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
840 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
842 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64
845 INTERCEPTOR(int, pipe
, int pipefd
[2]) {
846 if (msan_init_is_running
)
847 return REAL(pipe
)(pipefd
);
848 ENSURE_MSAN_INITED();
849 int res
= REAL(pipe
)(pipefd
);
851 __msan_unpoison(pipefd
, sizeof(int[2]));
855 INTERCEPTOR(int, pipe2
, int pipefd
[2], int flags
) {
856 ENSURE_MSAN_INITED();
857 int res
= REAL(pipe2
)(pipefd
, flags
);
859 __msan_unpoison(pipefd
, sizeof(int[2]));
863 INTERCEPTOR(int, socketpair
, int domain
, int type
, int protocol
, int sv
[2]) {
864 ENSURE_MSAN_INITED();
865 int res
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
867 __msan_unpoison(sv
, sizeof(int[2]));
871 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
872 INTERCEPTOR(char *, fgets_unlocked
, char *s
, int size
, void *stream
) {
873 ENSURE_MSAN_INITED();
874 char *res
= REAL(fgets_unlocked
)(s
, size
, stream
);
876 __msan_unpoison(s
, internal_strlen(s
) + 1);
879 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
881 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
884 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
885 if (msan_init_is_running) \
886 return REAL(getrlimit)(resource, rlim); \
887 ENSURE_MSAN_INITED(); \
888 int res = REAL(func)(resource, rlim); \
890 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
893 INTERCEPTOR(int, getrlimit
, int resource
, void *rlim
) {
894 INTERCEPTOR_GETRLIMIT_BODY(getrlimit
, resource
, rlim
);
897 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
898 INTERCEPTOR(int, __getrlimit
, int resource
, void *rlim
) {
899 INTERCEPTOR_GETRLIMIT_BODY(__getrlimit
, resource
, rlim
);
902 INTERCEPTOR(int, getrlimit64
, int resource
, void *rlim
) {
903 if (msan_init_is_running
) return REAL(getrlimit64
)(resource
, rlim
);
904 ENSURE_MSAN_INITED();
905 int res
= REAL(getrlimit64
)(resource
, rlim
);
906 if (!res
) __msan_unpoison(rlim
, __sanitizer::struct_rlimit64_sz
);
910 INTERCEPTOR(int, prlimit
, int pid
, int resource
, void *new_rlimit
,
912 if (msan_init_is_running
)
913 return REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
914 ENSURE_MSAN_INITED();
915 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit_sz
);
916 int res
= REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
917 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit_sz
);
921 INTERCEPTOR(int, prlimit64
, int pid
, int resource
, void *new_rlimit
,
923 if (msan_init_is_running
)
924 return REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
925 ENSURE_MSAN_INITED();
926 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit64_sz
);
927 int res
= REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
928 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit64_sz
);
932 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
933 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
934 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
935 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
937 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
938 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
939 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
940 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
943 INTERCEPTOR(int, gethostname
, char *name
, SIZE_T len
) {
944 ENSURE_MSAN_INITED();
945 int res
= REAL(gethostname
)(name
, len
);
946 if (!res
|| (res
== -1 && errno
== errno_ENAMETOOLONG
)) {
947 SIZE_T real_len
= internal_strnlen(name
, len
);
950 __msan_unpoison(name
, real_len
);
955 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
956 INTERCEPTOR(int, epoll_wait
, int epfd
, void *events
, int maxevents
,
958 ENSURE_MSAN_INITED();
959 int res
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
961 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
965 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
967 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
970 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
971 INTERCEPTOR(int, epoll_pwait
, int epfd
, void *events
, int maxevents
,
972 int timeout
, void *sigmask
) {
973 ENSURE_MSAN_INITED();
974 int res
= REAL(epoll_pwait
)(epfd
, events
, maxevents
, timeout
, sigmask
);
976 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
980 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
982 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
985 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
986 GET_MALLOC_STACK_TRACE
;
987 if (DlsymAlloc::Use())
988 return DlsymAlloc::Callocate(nmemb
, size
);
989 return msan_calloc(nmemb
, size
, &stack
);
992 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
993 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr
))
994 return DlsymAlloc::Realloc(ptr
, size
);
995 GET_MALLOC_STACK_TRACE
;
996 return msan_realloc(ptr
, size
, &stack
);
999 INTERCEPTOR(void *, reallocarray
, void *ptr
, SIZE_T nmemb
, SIZE_T size
) {
1000 GET_MALLOC_STACK_TRACE
;
1001 return msan_reallocarray(ptr
, nmemb
, size
, &stack
);
1004 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
1005 if (DlsymAlloc::Use())
1006 return DlsymAlloc::Allocate(size
);
1007 GET_MALLOC_STACK_TRACE
;
1008 return msan_malloc(size
, &stack
);
1011 void __msan_allocated_memory(const void *data
, uptr size
) {
1012 if (flags()->poison_in_malloc
) {
1013 GET_MALLOC_STACK_TRACE
;
1014 stack
.tag
= STACK_TRACE_TAG_POISON
;
1015 PoisonMemory(data
, size
, &stack
);
1019 void __msan_copy_shadow(void *dest
, const void *src
, uptr n
) {
1020 GET_STORE_STACK_TRACE
;
1021 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1024 void __sanitizer_dtor_callback(const void *data
, uptr size
) {
1025 if (flags()->poison_in_dtor
) {
1026 GET_MALLOC_STACK_TRACE
;
1027 stack
.tag
= STACK_TRACE_TAG_POISON
;
1028 PoisonMemory(data
, size
, &stack
);
1032 void __sanitizer_dtor_callback_fields(const void *data
, uptr size
) {
1033 if (flags()->poison_in_dtor
) {
1034 GET_MALLOC_STACK_TRACE
;
1035 stack
.tag
= STACK_TRACE_TAG_FIELDS
;
1036 PoisonMemory(data
, size
, &stack
);
1040 void __sanitizer_dtor_callback_vptr(const void *data
) {
1041 if (flags()->poison_in_dtor
) {
1042 GET_MALLOC_STACK_TRACE
;
1043 stack
.tag
= STACK_TRACE_TAG_VPTR
;
1044 PoisonMemory(data
, sizeof(void *), &stack
);
1048 template <class Mmap
>
1049 static void *mmap_interceptor(Mmap real_mmap
, void *addr
, SIZE_T length
,
1050 int prot
, int flags
, int fd
, OFF64_T offset
) {
1051 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
1052 void *end_addr
= (char *)addr
+ (rounded_length
- 1);
1053 if (addr
&& (!MEM_IS_APP(addr
) || !MEM_IS_APP(end_addr
))) {
1054 if (flags
& map_fixed
) {
1055 errno
= errno_EINVAL
;
1061 void *res
= real_mmap(addr
, length
, prot
, flags
, fd
, offset
);
1062 if (res
!= (void *)-1) {
1063 void *end_res
= (char *)res
+ (rounded_length
- 1);
1064 if (MEM_IS_APP(res
) && MEM_IS_APP(end_res
)) {
1065 __msan_unpoison(res
, rounded_length
);
1067 // Application has attempted to map more memory than is supported by
1068 // MSAN. Act as if we ran out of memory.
1069 internal_munmap(res
, length
);
1070 errno
= errno_ENOMEM
;
1077 INTERCEPTOR(int, getrusage
, int who
, void *usage
) {
1078 ENSURE_MSAN_INITED();
1079 int res
= REAL(getrusage
)(who
, usage
);
1081 __msan_unpoison(usage
, __sanitizer::struct_rusage_sz
);
1086 class SignalHandlerScope
{
1088 SignalHandlerScope() {
1089 if (MsanThread
*t
= GetCurrentThread())
1090 t
->EnterSignalHandler();
1092 ~SignalHandlerScope() {
1093 if (MsanThread
*t
= GetCurrentThread())
1094 t
->LeaveSignalHandler();
1098 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1099 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1100 // the signal handler.
1101 const int kMaxSignals
= 1024;
1102 static atomic_uintptr_t sigactions
[kMaxSignals
];
1103 static StaticSpinMutex sigactions_mu
;
1105 static void SignalHandler(int signo
) {
1106 SignalHandlerScope signal_handler_scope
;
1107 ScopedThreadLocalStateBackup stlsb
;
1110 typedef void (*signal_cb
)(int x
);
1112 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1116 static void SignalAction(int signo
, void *si
, void *uc
) {
1117 SignalHandlerScope signal_handler_scope
;
1118 ScopedThreadLocalStateBackup stlsb
;
1120 __msan_unpoison(si
, sizeof(__sanitizer_sigaction
));
1121 __msan_unpoison(uc
, ucontext_t_sz(uc
));
1123 typedef void (*sigaction_cb
)(int, void *, void *);
1125 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1127 CHECK_UNPOISONED(uc
, ucontext_t_sz(uc
));
1130 static void read_sigaction(const __sanitizer_sigaction
*act
) {
1131 CHECK_UNPOISONED(&act
->sa_flags
, sizeof(act
->sa_flags
));
1132 if (act
->sa_flags
& __sanitizer::sa_siginfo
)
1133 CHECK_UNPOISONED(&act
->sigaction
, sizeof(act
->sigaction
));
1135 CHECK_UNPOISONED(&act
->handler
, sizeof(act
->handler
));
1136 CHECK_UNPOISONED(&act
->sa_mask
, sizeof(act
->sa_mask
));
1139 extern "C" int pthread_attr_init(void *attr
);
1140 extern "C" int pthread_attr_destroy(void *attr
);
1142 static void *MsanThreadStartFunc(void *arg
) {
1143 MsanThread
*t
= (MsanThread
*)arg
;
1144 SetCurrentThread(t
);
1146 SetSigProcMask(&t
->starting_sigset_
, nullptr);
1147 return t
->ThreadStart();
1150 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
, void *(*callback
)(void*),
1152 ENSURE_MSAN_INITED(); // for GetTlsSize()
1153 __sanitizer_pthread_attr_t myattr
;
1155 pthread_attr_init(&myattr
);
1159 AdjustStackSize(attr
);
1161 MsanThread
*t
= MsanThread::Create(callback
, param
);
1162 ScopedBlockSignals
block(&t
->starting_sigset_
);
1163 int res
= REAL(pthread_create
)(th
, attr
, MsanThreadStartFunc
, t
);
1165 if (attr
== &myattr
)
1166 pthread_attr_destroy(&myattr
);
1168 __msan_unpoison(th
, __sanitizer::pthread_t_sz
);
1173 INTERCEPTOR(int, pthread_key_create
, __sanitizer_pthread_key_t
*key
,
1174 void (*dtor
)(void *value
)) {
1175 if (msan_init_is_running
) return REAL(pthread_key_create
)(key
, dtor
);
1176 ENSURE_MSAN_INITED();
1177 int res
= REAL(pthread_key_create
)(key
, dtor
);
1179 __msan_unpoison(key
, sizeof(*key
));
1183 #if SANITIZER_NETBSD
1184 INTERCEPTOR(int, __libc_thr_keycreate
, __sanitizer_pthread_key_t
*m
,
1185 void (*dtor
)(void *value
))
1186 ALIAS(WRAP(pthread_key_create
));
1189 INTERCEPTOR(int, pthread_join
, void *thread
, void **retval
) {
1190 ENSURE_MSAN_INITED();
1191 int res
= REAL(pthread_join
)(thread
, retval
);
1193 __msan_unpoison(retval
, sizeof(*retval
));
1198 INTERCEPTOR(int, pthread_tryjoin_np
, void *thread
, void **retval
) {
1199 ENSURE_MSAN_INITED();
1200 int res
= REAL(pthread_tryjoin_np
)(thread
, retval
);
1202 __msan_unpoison(retval
, sizeof(*retval
));
1206 INTERCEPTOR(int, pthread_timedjoin_np
, void *thread
, void **retval
,
1207 const struct timespec
*abstime
) {
1208 int res
= REAL(pthread_timedjoin_np
)(thread
, retval
, abstime
);
1210 __msan_unpoison(retval
, sizeof(*retval
));
1215 DEFINE_REAL_PTHREAD_FUNCTIONS
1217 extern char *tzname
[2];
1219 INTERCEPTOR(void, tzset
, int fake
) {
1220 ENSURE_MSAN_INITED();
1221 InterceptorScope interceptor_scope
;
1224 __msan_unpoison(tzname
[0], internal_strlen(tzname
[0]) + 1);
1226 __msan_unpoison(tzname
[1], internal_strlen(tzname
[1]) + 1);
1230 struct MSanAtExitRecord
{
1231 void (*func
)(void *arg
);
1235 struct InterceptorContext
{
1237 Vector
<struct MSanAtExitRecord
*> AtExitStack
;
1239 InterceptorContext()
1244 static ALIGNED(64) char interceptor_placeholder
[sizeof(InterceptorContext
)];
1245 InterceptorContext
*interceptor_ctx() {
1246 return reinterpret_cast<InterceptorContext
*>(&interceptor_placeholder
[0]);
1249 void MSanAtExitWrapper() {
1250 MSanAtExitRecord
*r
;
1252 Lock
l(&interceptor_ctx()->atexit_mu
);
1254 uptr element
= interceptor_ctx()->AtExitStack
.Size() - 1;
1255 r
= interceptor_ctx()->AtExitStack
[element
];
1256 interceptor_ctx()->AtExitStack
.PopBack();
1260 ((void(*)())r
->func
)();
1264 void MSanCxaAtExitWrapper(void *arg
) {
1266 MSanAtExitRecord
*r
= (MSanAtExitRecord
*)arg
;
1267 // libc before 2.27 had race which caused occasional double handler execution
1268 // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1275 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
);
1277 // Unpoison argument shadow for C++ module destructors.
1278 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
1280 if (msan_init_is_running
) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
1281 return setup_at_exit_wrapper((void(*)())func
, arg
, dso_handle
);
1284 // Unpoison argument shadow for C++ module destructors.
1285 INTERCEPTOR(int, atexit
, void (*func
)()) {
1286 // Avoid calling real atexit as it is unreachable on at least on Linux.
1287 if (msan_init_is_running
)
1288 return REAL(__cxa_atexit
)((void (*)(void *a
))func
, 0, 0);
1289 return setup_at_exit_wrapper((void(*)())func
, 0, 0);
1292 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
) {
1293 ENSURE_MSAN_INITED();
1294 MSanAtExitRecord
*r
=
1295 (MSanAtExitRecord
*)InternalAlloc(sizeof(MSanAtExitRecord
));
1296 r
->func
= (void(*)(void *a
))f
;
1300 // NetBSD does not preserve the 2nd argument if dso is equal to 0
1301 // Store ctx in a local stack-like structure
1303 Lock
l(&interceptor_ctx()->atexit_mu
);
1305 res
= REAL(__cxa_atexit
)((void (*)(void *a
))MSanAtExitWrapper
, 0, 0);
1307 interceptor_ctx()->AtExitStack
.PushBack(r
);
1310 res
= REAL(__cxa_atexit
)(MSanCxaAtExitWrapper
, r
, dso
);
1315 static void BeforeFork() {
1316 StackDepotLockAll();
1317 ChainedOriginDepotLockAll();
1320 static void AfterFork() {
1321 ChainedOriginDepotUnlockAll();
1322 StackDepotUnlockAll();
1325 INTERCEPTOR(int, fork
, void) {
1326 ENSURE_MSAN_INITED();
1328 int pid
= REAL(fork
)();
1333 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1336 INTERCEPTOR(int, openpty
, int *aparent
, int *aworker
, char *name
,
1337 const void *termp
, const void *winp
) {
1338 ENSURE_MSAN_INITED();
1339 InterceptorScope interceptor_scope
;
1340 int res
= REAL(openpty
)(aparent
, aworker
, name
, termp
, winp
);
1342 __msan_unpoison(aparent
, sizeof(*aparent
));
1343 __msan_unpoison(aworker
, sizeof(*aworker
));
1347 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1349 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1352 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1355 INTERCEPTOR(int, forkpty
, int *aparent
, char *name
, const void *termp
,
1357 ENSURE_MSAN_INITED();
1358 InterceptorScope interceptor_scope
;
1359 int res
= REAL(forkpty
)(aparent
, name
, termp
, winp
);
1361 __msan_unpoison(aparent
, sizeof(*aparent
));
1364 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1366 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1369 struct MSanInterceptorContext
{
1370 bool in_interceptor_scope
;
1376 // FIXME: ask frontend whether we need to return failure.
1380 } // namespace __msan
1382 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1384 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1386 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1387 CHECK_UNPOISONED_0(x, n); \
1390 #define MSAN_INTERCEPT_FUNC(name) \
1392 if (!INTERCEPT_FUNCTION(name)) \
1393 VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1396 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1398 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
1399 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1402 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
1404 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
1405 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1406 #name, ver, #name); \
1409 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1410 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1411 MSAN_INTERCEPT_FUNC_VER(name, ver)
1412 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1413 MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1414 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1415 UnpoisonParam(count)
1416 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1417 __msan_unpoison(ptr, size)
1418 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1419 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1420 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1421 __msan_unpoison(ptr, size)
1422 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1423 if (msan_init_is_running) \
1424 return REAL(func)(__VA_ARGS__); \
1425 ENSURE_MSAN_INITED(); \
1426 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1427 ctx = (void *)&msan_ctx; \
1429 InterceptorScope interceptor_scope; \
1430 __msan_unpoison(__errno_location(), sizeof(int));
1431 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1434 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1437 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1440 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1443 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1445 } while (false) // FIXME
1446 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1448 } while (false) // FIXME
1449 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1450 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1451 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1453 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1454 if (filename && map) \
1455 ForEachMappedRegion(map, __msan_unpoison); \
1458 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1460 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1461 if (MsanThread *t = GetCurrentThread()) { \
1462 *begin = t->tls_begin(); \
1463 *end = t->tls_end(); \
1465 *begin = *end = 0; \
1468 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1471 return __msan_memset(block, c, size); \
1473 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1476 return __msan_memmove(to, from, size); \
1478 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1481 return __msan_memcpy(to, from, size); \
1484 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1486 GET_STORE_STACK_TRACE; \
1487 CopyShadowAndOrigin(to, from, size, &stack); \
1488 __msan_unpoison(to + size, 1); \
1491 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1494 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
1497 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1498 #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
1499 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1501 static uptr
signal_impl(int signo
, uptr cb
);
1502 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1503 __sanitizer_sigaction
*oldact
);
1505 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1506 { return sigaction_impl(signo, act, oldact); }
1508 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1510 handler = signal_impl(signo, handler); \
1511 InterceptorScope interceptor_scope; \
1512 return REAL(func)(signo, handler); \
1515 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
1517 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1519 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1520 __sanitizer_sigaction
*oldact
) {
1521 ENSURE_MSAN_INITED();
1522 if (signo
<= 0 || signo
>= kMaxSignals
) {
1523 errno
= errno_EINVAL
;
1526 if (act
) read_sigaction(act
);
1528 if (flags()->wrap_signals
) {
1529 SpinMutexLock
lock(&sigactions_mu
);
1530 uptr old_cb
= atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1531 __sanitizer_sigaction new_act
;
1532 __sanitizer_sigaction
*pnew_act
= act
? &new_act
: nullptr;
1534 REAL(memcpy
)(pnew_act
, act
, sizeof(__sanitizer_sigaction
));
1535 uptr cb
= (uptr
)pnew_act
->sigaction
;
1536 uptr new_cb
= (pnew_act
->sa_flags
& __sanitizer::sa_siginfo
)
1537 ? (uptr
)SignalAction
1538 : (uptr
)SignalHandler
;
1539 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1540 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1541 pnew_act
->sigaction
= (decltype(pnew_act
->sigaction
))new_cb
;
1544 res
= REAL(SIGACTION_SYMNAME
)(signo
, pnew_act
, oldact
);
1545 if (res
== 0 && oldact
) {
1546 uptr cb
= (uptr
)oldact
->sigaction
;
1547 if (cb
== (uptr
)SignalAction
|| cb
== (uptr
)SignalHandler
) {
1548 oldact
->sigaction
= (decltype(oldact
->sigaction
))old_cb
;
1552 res
= REAL(SIGACTION_SYMNAME
)(signo
, act
, oldact
);
1555 if (res
== 0 && oldact
) {
1556 __msan_unpoison(oldact
, sizeof(__sanitizer_sigaction
));
1561 static uptr
signal_impl(int signo
, uptr cb
) {
1562 ENSURE_MSAN_INITED();
1563 if (signo
<= 0 || signo
>= kMaxSignals
) {
1564 errno
= errno_EINVAL
;
1567 if (flags()->wrap_signals
) {
1568 SpinMutexLock
lock(&sigactions_mu
);
1569 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1570 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1571 cb
= (uptr
)&SignalHandler
;
1577 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1578 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1581 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1584 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1585 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1586 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1588 INTERCEPTOR(const char *, strsignal
, int sig
) {
1590 COMMON_INTERCEPTOR_ENTER(ctx
, strsignal
, sig
);
1591 const char *res
= REAL(strsignal
)(sig
);
1593 __msan_unpoison(res
, internal_strlen(res
) + 1);
1597 INTERCEPTOR(int, dladdr
, void *addr
, void *info
) {
1599 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr
, addr
, info
);
1600 int res
= REAL(dladdr
)(addr
, info
);
1602 UnpoisonDllAddrInfo(info
);
1607 INTERCEPTOR(int, dladdr1
, void *addr
, void *info
, void **extra_info
,
1610 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr1
, addr
, info
, extra_info
, flags
);
1611 int res
= REAL(dladdr1
)(addr
, info
, extra_info
, flags
);
1613 UnpoisonDllAddrInfo(info
);
1614 UnpoisonDllAddr1ExtraInfo(extra_info
, flags
);
1618 # define MSAN_MAYBE_INTERCEPT_DLADDR1 MSAN_INTERCEPT_FUNC(dladdr1)
1620 #define MSAN_MAYBE_INTERCEPT_DLADDR1
1623 INTERCEPTOR(char *, dlerror
, int fake
) {
1625 COMMON_INTERCEPTOR_ENTER(ctx
, dlerror
, fake
);
1626 char *res
= REAL(dlerror
)(fake
);
1628 __msan_unpoison(res
, internal_strlen(res
) + 1);
1632 typedef int (*dl_iterate_phdr_cb
)(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1634 struct dl_iterate_phdr_data
{
1635 dl_iterate_phdr_cb callback
;
1639 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1642 __msan_unpoison(info
, size
);
1643 if (info
->dlpi_phdr
&& info
->dlpi_phnum
)
1644 __msan_unpoison(info
->dlpi_phdr
, struct_ElfW_Phdr_sz
* info
->dlpi_phnum
);
1645 if (info
->dlpi_name
)
1646 __msan_unpoison(info
->dlpi_name
, internal_strlen(info
->dlpi_name
) + 1);
1648 dl_iterate_phdr_data
*cbdata
= (dl_iterate_phdr_data
*)data
;
1650 return cbdata
->callback(info
, size
, cbdata
->data
);
1653 INTERCEPTOR(void *, shmat
, int shmid
, const void *shmaddr
, int shmflg
) {
1654 ENSURE_MSAN_INITED();
1655 void *p
= REAL(shmat
)(shmid
, shmaddr
, shmflg
);
1656 if (p
!= (void *)-1) {
1657 __sanitizer_shmid_ds ds
;
1658 int res
= REAL(shmctl
)(shmid
, shmctl_ipc_stat
, &ds
);
1660 __msan_unpoison(p
, ds
.shm_segsz
);
1666 INTERCEPTOR(int, dl_iterate_phdr
, dl_iterate_phdr_cb callback
, void *data
) {
1668 COMMON_INTERCEPTOR_ENTER(ctx
, dl_iterate_phdr
, callback
, data
);
1669 dl_iterate_phdr_data cbdata
;
1670 cbdata
.callback
= callback
;
1672 int res
= REAL(dl_iterate_phdr
)(msan_dl_iterate_phdr_cb
, (void *)&cbdata
);
1676 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
1677 INTERCEPTOR(wchar_t *, wcschr
, void *s
, wchar_t wc
, void *ps
) {
1678 ENSURE_MSAN_INITED();
1679 wchar_t *res
= REAL(wcschr
)(s
, wc
, ps
);
1683 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
1684 INTERCEPTOR(wchar_t *, wcscpy
, wchar_t *dest
, const wchar_t *src
) {
1685 ENSURE_MSAN_INITED();
1686 GET_STORE_STACK_TRACE
;
1687 wchar_t *res
= REAL(wcscpy
)(dest
, src
);
1688 CopyShadowAndOrigin(dest
, src
, sizeof(wchar_t) * (internal_wcslen(src
) + 1),
1693 INTERCEPTOR(wchar_t *, wcsncpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
1694 ENSURE_MSAN_INITED();
1695 GET_STORE_STACK_TRACE
;
1696 SIZE_T copy_size
= internal_wcsnlen(src
, n
);
1697 if (copy_size
< n
) copy_size
++; // trailing \0
1698 wchar_t *res
= REAL(wcsncpy
)(dest
, src
, n
);
1699 CopyShadowAndOrigin(dest
, src
, copy_size
* sizeof(wchar_t), &stack
);
1700 __msan_unpoison(dest
+ copy_size
, (n
- copy_size
) * sizeof(wchar_t));
1704 // These interface functions reside here so that they can use
1705 // REAL(memset), etc.
1706 void __msan_unpoison(const void *a
, uptr size
) {
1707 if (!MEM_IS_APP(a
)) return;
1708 SetShadow(a
, size
, 0);
1711 void __msan_poison(const void *a
, uptr size
) {
1712 if (!MEM_IS_APP(a
)) return;
1713 SetShadow(a
, size
, __msan::flags()->poison_heap_with_zeroes
? 0 : -1);
1716 void __msan_poison_stack(void *a
, uptr size
) {
1717 if (!MEM_IS_APP(a
)) return;
1718 SetShadow(a
, size
, __msan::flags()->poison_stack_with_zeroes
? 0 : -1);
1721 void __msan_unpoison_param(uptr n
) { UnpoisonParam(n
); }
1723 void __msan_clear_and_unpoison(void *a
, uptr size
) {
1724 REAL(memset
)(a
, 0, size
);
1725 SetShadow(a
, size
, 0);
1728 void *__msan_memcpy(void *dest
, const void *src
, SIZE_T n
) {
1729 if (!msan_inited
) return internal_memcpy(dest
, src
, n
);
1730 if (msan_init_is_running
|| __msan::IsInSymbolizerOrUnwider())
1731 return REAL(memcpy
)(dest
, src
, n
);
1732 ENSURE_MSAN_INITED();
1733 GET_STORE_STACK_TRACE
;
1734 void *res
= REAL(memcpy
)(dest
, src
, n
);
1735 CopyShadowAndOrigin(dest
, src
, n
, &stack
);
1739 void *__msan_memset(void *s
, int c
, SIZE_T n
) {
1740 if (!msan_inited
) return internal_memset(s
, c
, n
);
1741 if (msan_init_is_running
) return REAL(memset
)(s
, c
, n
);
1742 ENSURE_MSAN_INITED();
1743 void *res
= REAL(memset
)(s
, c
, n
);
1744 __msan_unpoison(s
, n
);
1748 void *__msan_memmove(void *dest
, const void *src
, SIZE_T n
) {
1749 if (!msan_inited
) return internal_memmove(dest
, src
, n
);
1750 if (msan_init_is_running
) return REAL(memmove
)(dest
, src
, n
);
1751 ENSURE_MSAN_INITED();
1752 GET_STORE_STACK_TRACE
;
1753 void *res
= REAL(memmove
)(dest
, src
, n
);
1754 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1758 void __msan_unpoison_string(const char* s
) {
1759 if (!MEM_IS_APP(s
)) return;
1760 __msan_unpoison(s
, internal_strlen(s
) + 1);
1765 void InitializeInterceptors() {
1766 static int inited
= 0;
1767 CHECK_EQ(inited
, 0);
1769 new(interceptor_ctx()) InterceptorContext();
1771 InitializeCommonInterceptors();
1772 InitializeSignalInterceptors();
1774 INTERCEPT_FUNCTION(posix_memalign
);
1775 MSAN_MAYBE_INTERCEPT_MEMALIGN
;
1776 MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
;
1777 INTERCEPT_FUNCTION(valloc
);
1778 MSAN_MAYBE_INTERCEPT_PVALLOC
;
1779 INTERCEPT_FUNCTION(malloc
);
1780 INTERCEPT_FUNCTION(calloc
);
1781 INTERCEPT_FUNCTION(realloc
);
1782 INTERCEPT_FUNCTION(reallocarray
);
1783 INTERCEPT_FUNCTION(free
);
1784 MSAN_MAYBE_INTERCEPT_CFREE
;
1785 MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
;
1786 MSAN_MAYBE_INTERCEPT_MALLINFO
;
1787 MSAN_MAYBE_INTERCEPT_MALLOPT
;
1788 MSAN_MAYBE_INTERCEPT_MALLOC_STATS
;
1789 INTERCEPT_FUNCTION(fread
);
1790 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
;
1791 INTERCEPT_FUNCTION(memccpy
);
1792 MSAN_MAYBE_INTERCEPT_MEMPCPY
;
1793 INTERCEPT_FUNCTION(bcopy
);
1794 INTERCEPT_FUNCTION(wmemset
);
1795 INTERCEPT_FUNCTION(wmemcpy
);
1796 MSAN_MAYBE_INTERCEPT_WMEMPCPY
;
1797 INTERCEPT_FUNCTION(wmemmove
);
1798 INTERCEPT_FUNCTION(strcpy
);
1799 MSAN_MAYBE_INTERCEPT_STPCPY
;
1800 MSAN_MAYBE_INTERCEPT_STPNCPY
;
1801 INTERCEPT_FUNCTION(strdup
);
1802 MSAN_MAYBE_INTERCEPT___STRDUP
;
1803 INTERCEPT_FUNCTION(strncpy
);
1804 MSAN_MAYBE_INTERCEPT_GCVT
;
1805 INTERCEPT_FUNCTION(strcat
);
1806 INTERCEPT_FUNCTION(strncat
);
1807 INTERCEPT_STRTO(strtod
);
1808 INTERCEPT_STRTO(strtof
);
1809 #ifdef SANITIZER_NLDBL_VERSION
1810 INTERCEPT_STRTO_VER(strtold
, SANITIZER_NLDBL_VERSION
);
1812 INTERCEPT_STRTO(strtold
);
1814 INTERCEPT_STRTO(strtol
);
1815 INTERCEPT_STRTO(strtoul
);
1816 INTERCEPT_STRTO(strtoll
);
1817 INTERCEPT_STRTO(strtoull
);
1818 INTERCEPT_STRTO(strtouq
);
1819 INTERCEPT_STRTO(wcstod
);
1820 INTERCEPT_STRTO(wcstof
);
1821 #ifdef SANITIZER_NLDBL_VERSION
1822 INTERCEPT_STRTO_VER(wcstold
, SANITIZER_NLDBL_VERSION
);
1824 INTERCEPT_STRTO(wcstold
);
1826 INTERCEPT_STRTO(wcstol
);
1827 INTERCEPT_STRTO(wcstoul
);
1828 INTERCEPT_STRTO(wcstoll
);
1829 INTERCEPT_STRTO(wcstoull
);
1831 INTERCEPT_STRTO(__isoc23_strtod
);
1832 INTERCEPT_STRTO(__isoc23_strtof
);
1833 INTERCEPT_STRTO(__isoc23_strtold
);
1834 INTERCEPT_STRTO(__isoc23_strtol
);
1835 INTERCEPT_STRTO(__isoc23_strtoul
);
1836 INTERCEPT_STRTO(__isoc23_strtoll
);
1837 INTERCEPT_STRTO(__isoc23_strtoull
);
1838 INTERCEPT_STRTO(__isoc23_strtouq
);
1839 INTERCEPT_STRTO(__isoc23_wcstod
);
1840 INTERCEPT_STRTO(__isoc23_wcstof
);
1841 INTERCEPT_STRTO(__isoc23_wcstold
);
1842 INTERCEPT_STRTO(__isoc23_wcstol
);
1843 INTERCEPT_STRTO(__isoc23_wcstoul
);
1844 INTERCEPT_STRTO(__isoc23_wcstoll
);
1845 INTERCEPT_STRTO(__isoc23_wcstoull
);
1848 #ifdef SANITIZER_NLDBL_VERSION
1849 INTERCEPT_FUNCTION_VER(vswprintf
, SANITIZER_NLDBL_VERSION
);
1850 INTERCEPT_FUNCTION_VER(swprintf
, SANITIZER_NLDBL_VERSION
);
1852 INTERCEPT_FUNCTION(vswprintf
);
1853 INTERCEPT_FUNCTION(swprintf
);
1855 INTERCEPT_FUNCTION(strftime
);
1856 INTERCEPT_FUNCTION(strftime_l
);
1857 MSAN_MAYBE_INTERCEPT___STRFTIME_L
;
1858 INTERCEPT_FUNCTION(wcsftime
);
1859 INTERCEPT_FUNCTION(wcsftime_l
);
1860 MSAN_MAYBE_INTERCEPT___WCSFTIME_L
;
1861 INTERCEPT_FUNCTION(mbtowc
);
1862 INTERCEPT_FUNCTION(mbrtowc
);
1863 INTERCEPT_FUNCTION(wcslen
);
1864 INTERCEPT_FUNCTION(wcsnlen
);
1865 INTERCEPT_FUNCTION(wcschr
);
1866 INTERCEPT_FUNCTION(wcscpy
);
1867 INTERCEPT_FUNCTION(wcsncpy
);
1868 INTERCEPT_FUNCTION(wcscmp
);
1869 INTERCEPT_FUNCTION(getenv
);
1870 INTERCEPT_FUNCTION(setenv
);
1871 INTERCEPT_FUNCTION(putenv
);
1872 INTERCEPT_FUNCTION(gettimeofday
);
1873 MSAN_MAYBE_INTERCEPT_FCVT
;
1874 MSAN_MAYBE_INTERCEPT_FSTAT
;
1875 MSAN_MAYBE_INTERCEPT_FSTAT64
;
1876 MSAN_MAYBE_INTERCEPT___FXSTAT
;
1877 MSAN_MAYBE_INTERCEPT_FSTATAT
;
1878 MSAN_MAYBE_INTERCEPT_FSTATAT64
;
1879 MSAN_MAYBE_INTERCEPT___FXSTATAT
;
1880 MSAN_MAYBE_INTERCEPT___FXSTAT64
;
1881 MSAN_MAYBE_INTERCEPT___FXSTATAT64
;
1882 INTERCEPT_FUNCTION(pipe
);
1883 INTERCEPT_FUNCTION(pipe2
);
1884 INTERCEPT_FUNCTION(socketpair
);
1885 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
;
1886 INTERCEPT_FUNCTION(getrlimit
);
1887 MSAN_MAYBE_INTERCEPT___GETRLIMIT
;
1888 MSAN_MAYBE_INTERCEPT_GETRLIMIT64
;
1889 MSAN_MAYBE_INTERCEPT_PRLIMIT
;
1890 MSAN_MAYBE_INTERCEPT_PRLIMIT64
;
1891 INTERCEPT_FUNCTION(gethostname
);
1892 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
;
1893 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
;
1894 INTERCEPT_FUNCTION(strsignal
);
1895 INTERCEPT_FUNCTION(dladdr
);
1896 MSAN_MAYBE_INTERCEPT_DLADDR1
;
1897 INTERCEPT_FUNCTION(dlerror
);
1898 INTERCEPT_FUNCTION(dl_iterate_phdr
);
1899 INTERCEPT_FUNCTION(getrusage
);
1900 #if defined(__mips__)
1901 INTERCEPT_FUNCTION_VER(pthread_create
, "GLIBC_2.2");
1903 INTERCEPT_FUNCTION(pthread_create
);
1905 INTERCEPT_FUNCTION(pthread_join
);
1906 INTERCEPT_FUNCTION(pthread_key_create
);
1908 INTERCEPT_FUNCTION(pthread_tryjoin_np
);
1909 INTERCEPT_FUNCTION(pthread_timedjoin_np
);
1912 #if SANITIZER_NETBSD
1913 INTERCEPT_FUNCTION(__libc_thr_keycreate
);
1916 INTERCEPT_FUNCTION(pthread_join
);
1917 INTERCEPT_FUNCTION(tzset
);
1918 INTERCEPT_FUNCTION(atexit
);
1919 INTERCEPT_FUNCTION(__cxa_atexit
);
1920 INTERCEPT_FUNCTION(shmat
);
1921 INTERCEPT_FUNCTION(fork
);
1922 MSAN_MAYBE_INTERCEPT_OPENPTY
;
1923 MSAN_MAYBE_INTERCEPT_FORKPTY
;
1927 } // namespace __msan