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_vector.h"
43 #define fstat __fstat50
44 #define gettimeofday __gettimeofday50
45 #define getrusage __getrusage50
46 #define tzset __tzset50
50 // ACHTUNG! No other system header includes in this file.
51 // Ideally, we should get rid of stdarg.h as well.
53 using namespace __msan
;
55 using __sanitizer::memory_order
;
56 using __sanitizer::atomic_load
;
57 using __sanitizer::atomic_store
;
58 using __sanitizer::atomic_uintptr_t
;
60 DECLARE_REAL(SIZE_T
, strlen
, const char *s
)
61 DECLARE_REAL(SIZE_T
, strnlen
, const char *s
, SIZE_T maxlen
)
62 DECLARE_REAL(void *, memcpy
, void *dest
, const void *src
, uptr n
)
63 DECLARE_REAL(void *, memset
, void *dest
, int c
, uptr n
)
65 // True if this is a nested interceptor.
66 static THREADLOCAL
int in_interceptor_scope
;
68 void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope
; }
69 void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope
; }
71 struct InterceptorScope
{
72 InterceptorScope() { ++in_interceptor_scope
; }
73 ~InterceptorScope() { --in_interceptor_scope
; }
76 bool IsInInterceptorScope() {
77 return in_interceptor_scope
;
80 struct DlsymAlloc
: public DlSymAllocator
<DlsymAlloc
> {
81 static bool UseImpl() { return !msan_inited
; }
84 #define ENSURE_MSAN_INITED() do { \
85 CHECK(!msan_init_is_running); \
91 // Check that [x, x+n) range is unpoisoned.
92 #define CHECK_UNPOISONED_0(x, n) \
94 sptr __offset = __msan_test_shadow(x, n); \
95 if (__msan::IsInSymbolizerOrUnwider()) \
97 if (__offset >= 0 && __msan::flags()->report_umrs) { \
99 ReportUMRInsideAddressRange(__func__, x, n, __offset); \
100 __msan::PrintWarningWithOrigin( \
101 pc, bp, __msan_get_origin((const char *)x + __offset)); \
102 if (__msan::flags()->halt_on_error) { \
103 Printf("Exiting\n"); \
109 // Check that [x, x+n) range is unpoisoned unless we are in a nested
111 #define CHECK_UNPOISONED(x, n) \
113 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
116 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
117 CHECK_UNPOISONED((x), \
118 common_flags()->strict_string_checks ? (len) + 1 : (n) )
120 #define CHECK_UNPOISONED_STRING(x, n) \
121 CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
123 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
124 INTERCEPTOR(SIZE_T
, fread_unlocked
, void *ptr
, SIZE_T size
, SIZE_T nmemb
,
126 ENSURE_MSAN_INITED();
127 SIZE_T res
= REAL(fread_unlocked
)(ptr
, size
, nmemb
, file
);
129 __msan_unpoison(ptr
, res
*size
);
132 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
134 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
137 #if !SANITIZER_NETBSD
138 INTERCEPTOR(void *, mempcpy
, void *dest
, const void *src
, SIZE_T n
) {
139 return (char *)__msan_memcpy(dest
, src
, n
) + n
;
141 #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
143 #define MSAN_MAYBE_INTERCEPT_MEMPCPY
146 INTERCEPTOR(void *, memccpy
, void *dest
, const void *src
, int c
, SIZE_T n
) {
147 ENSURE_MSAN_INITED();
148 void *res
= REAL(memccpy
)(dest
, src
, c
, n
);
149 CHECK(!res
|| (res
>= dest
&& res
<= (char *)dest
+ n
));
150 SIZE_T sz
= res
? (char *)res
- (char *)dest
: n
;
151 CHECK_UNPOISONED(src
, sz
);
152 __msan_unpoison(dest
, sz
);
156 INTERCEPTOR(void *, bcopy
, const void *src
, void *dest
, SIZE_T n
) {
157 return __msan_memmove(dest
, src
, n
);
160 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
161 GET_MALLOC_STACK_TRACE
;
163 int res
= msan_posix_memalign(memptr
, alignment
, size
, &stack
);
165 __msan_unpoison(memptr
, sizeof(*memptr
));
169 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
170 INTERCEPTOR(void *, memalign
, SIZE_T alignment
, SIZE_T size
) {
171 GET_MALLOC_STACK_TRACE
;
172 return msan_memalign(alignment
, size
, &stack
);
174 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
176 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
179 INTERCEPTOR(void *, aligned_alloc
, SIZE_T alignment
, SIZE_T size
) {
180 GET_MALLOC_STACK_TRACE
;
181 return msan_aligned_alloc(alignment
, size
, &stack
);
184 #if !SANITIZER_NETBSD
185 INTERCEPTOR(void *, __libc_memalign
, SIZE_T alignment
, SIZE_T size
) {
186 GET_MALLOC_STACK_TRACE
;
187 return msan_memalign(alignment
, size
, &stack
);
189 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
191 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
194 INTERCEPTOR(void *, valloc
, SIZE_T size
) {
195 GET_MALLOC_STACK_TRACE
;
196 return msan_valloc(size
, &stack
);
199 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
200 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
201 GET_MALLOC_STACK_TRACE
;
202 return msan_pvalloc(size
, &stack
);
204 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
206 #define MSAN_MAYBE_INTERCEPT_PVALLOC
209 INTERCEPTOR(void, free
, void *ptr
) {
212 if (DlsymAlloc::PointerIsMine(ptr
))
213 return DlsymAlloc::Free(ptr
);
214 GET_MALLOC_STACK_TRACE
;
215 MsanDeallocate(&stack
, ptr
);
218 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
219 INTERCEPTOR(void, cfree
, void *ptr
) {
222 if (DlsymAlloc::PointerIsMine(ptr
))
223 return DlsymAlloc::Free(ptr
);
224 GET_MALLOC_STACK_TRACE
;
225 MsanDeallocate(&stack
, ptr
);
227 # define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
229 #define MSAN_MAYBE_INTERCEPT_CFREE
232 #if !SANITIZER_NETBSD
233 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
234 return __sanitizer_get_allocated_size(ptr
);
236 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
237 INTERCEPT_FUNCTION(malloc_usable_size)
239 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
242 #if (!SANITIZER_FREEBSD && !SANITIZER_NETBSD) || __GLIBC_PREREQ(2, 33)
244 static NOINLINE
void clear_mallinfo(T
*sret
) {
245 ENSURE_MSAN_INITED();
246 internal_memset(sret
, 0, sizeof(*sret
));
247 __msan_unpoison(sret
, sizeof(*sret
));
251 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
252 // Interceptors use NRVO and assume that sret will be pre-allocated in
254 INTERCEPTOR(__sanitizer_struct_mallinfo
, mallinfo
,) {
255 __sanitizer_struct_mallinfo sret
;
256 clear_mallinfo(&sret
);
259 # define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
261 # define MSAN_MAYBE_INTERCEPT_MALLINFO
264 #if __GLIBC_PREREQ(2, 33)
265 INTERCEPTOR(__sanitizer_struct_mallinfo2
, mallinfo2
) {
266 __sanitizer_struct_mallinfo2 sret
;
267 clear_mallinfo(&sret
);
270 # define MSAN_MAYBE_INTERCEPT_MALLINFO2 INTERCEPT_FUNCTION(mallinfo2)
272 # define MSAN_MAYBE_INTERCEPT_MALLINFO2
275 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
276 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
279 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
281 #define MSAN_MAYBE_INTERCEPT_MALLOPT
284 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
285 INTERCEPTOR(void, malloc_stats
, void) {
286 // FIXME: implement, but don't call REAL(malloc_stats)!
288 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
290 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
293 INTERCEPTOR(char *, strcpy
, char *dest
, const char *src
) {
294 ENSURE_MSAN_INITED();
295 GET_STORE_STACK_TRACE
;
296 SIZE_T n
= internal_strlen(src
);
297 CHECK_UNPOISONED_STRING(src
+ n
, 0);
298 char *res
= REAL(strcpy
)(dest
, src
);
299 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
303 INTERCEPTOR(char *, strncpy
, char *dest
, const char *src
, SIZE_T n
) {
304 ENSURE_MSAN_INITED();
305 GET_STORE_STACK_TRACE
;
306 SIZE_T copy_size
= internal_strnlen(src
, n
);
308 copy_size
++; // trailing \0
309 char *res
= REAL(strncpy
)(dest
, src
, n
);
310 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
311 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
315 #if !SANITIZER_NETBSD
316 INTERCEPTOR(char *, stpcpy
, char *dest
, const char *src
) {
317 ENSURE_MSAN_INITED();
318 GET_STORE_STACK_TRACE
;
319 SIZE_T n
= internal_strlen(src
);
320 CHECK_UNPOISONED_STRING(src
+ n
, 0);
321 char *res
= REAL(stpcpy
)(dest
, src
);
322 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
326 INTERCEPTOR(char *, stpncpy
, char *dest
, const char *src
, SIZE_T n
) {
327 ENSURE_MSAN_INITED();
328 GET_STORE_STACK_TRACE
;
329 SIZE_T copy_size
= Min(n
, internal_strnlen(src
, n
) + 1);
330 char *res
= REAL(stpncpy
)(dest
, src
, n
);
331 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
332 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
335 # define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
336 # define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
338 #define MSAN_MAYBE_INTERCEPT_STPCPY
339 # define MSAN_MAYBE_INTERCEPT_STPNCPY
342 INTERCEPTOR(char *, strdup
, char *src
) {
343 ENSURE_MSAN_INITED();
344 GET_STORE_STACK_TRACE
;
345 // On FreeBSD strdup() leverages strlen().
346 InterceptorScope interceptor_scope
;
347 SIZE_T n
= internal_strlen(src
);
348 CHECK_UNPOISONED_STRING(src
+ n
, 0);
349 char *res
= REAL(strdup
)(src
);
350 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
354 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
355 INTERCEPTOR(char *, __strdup
, char *src
) {
356 ENSURE_MSAN_INITED();
357 GET_STORE_STACK_TRACE
;
358 SIZE_T n
= internal_strlen(src
);
359 CHECK_UNPOISONED_STRING(src
+ n
, 0);
360 char *res
= REAL(__strdup
)(src
);
361 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
364 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
366 #define MSAN_MAYBE_INTERCEPT___STRDUP
369 #if !SANITIZER_NETBSD
370 INTERCEPTOR(char *, gcvt
, double number
, SIZE_T ndigit
, char *buf
) {
371 ENSURE_MSAN_INITED();
372 char *res
= REAL(gcvt
)(number
, ndigit
, buf
);
373 SIZE_T n
= internal_strlen(buf
);
374 __msan_unpoison(buf
, n
+ 1);
377 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
379 #define MSAN_MAYBE_INTERCEPT_GCVT
382 INTERCEPTOR(char *, strcat
, char *dest
, const char *src
) {
383 ENSURE_MSAN_INITED();
384 GET_STORE_STACK_TRACE
;
385 SIZE_T src_size
= internal_strlen(src
);
386 SIZE_T dest_size
= internal_strlen(dest
);
387 CHECK_UNPOISONED_STRING(src
+ src_size
, 0);
388 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
389 char *res
= REAL(strcat
)(dest
, src
);
390 CopyShadowAndOrigin(dest
+ dest_size
, src
, src_size
+ 1, &stack
);
394 INTERCEPTOR(char *, strncat
, char *dest
, const char *src
, SIZE_T n
) {
395 ENSURE_MSAN_INITED();
396 GET_STORE_STACK_TRACE
;
397 SIZE_T dest_size
= internal_strlen(dest
);
398 SIZE_T copy_size
= internal_strnlen(src
, n
);
399 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
400 char *res
= REAL(strncat
)(dest
, src
, n
);
401 CopyShadowAndOrigin(dest
+ dest_size
, src
, copy_size
, &stack
);
402 __msan_unpoison(dest
+ dest_size
+ copy_size
, 1); // \0
406 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
407 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
408 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
409 ENSURE_MSAN_INITED(); \
410 ret_type res = REAL(func)(__VA_ARGS__); \
411 __msan_unpoison(endptr, sizeof(*endptr)); \
414 // On s390x, long double return values are passed via implicit reference,
415 // which needs to be unpoisoned. We make the implicit pointer explicit.
416 #define INTERCEPTOR_STRTO_SRET_BODY(func, sret, ...) \
417 ENSURE_MSAN_INITED(); \
418 REAL(func)(sret, __VA_ARGS__); \
419 __msan_unpoison(sret, sizeof(*sret)); \
420 __msan_unpoison(endptr, sizeof(*endptr));
422 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
423 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
424 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
427 #define INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
428 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
429 char_type **endptr) { \
430 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr); \
433 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
434 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
436 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
439 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
440 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
442 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
445 #define INTERCEPTOR_STRTO_SRET_LOC(ret_type, func, char_type) \
446 INTERCEPTOR(void, func, ret_type *sret, const char_type *nptr, \
447 char_type **endptr, void *loc) { \
448 INTERCEPTOR_STRTO_SRET_BODY(func, sret, nptr, endptr, loc); \
451 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
452 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
453 int base, void *loc) { \
454 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
458 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
459 INTERCEPTOR_STRTO(ret_type, func, char_type) \
460 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
462 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
463 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
464 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type)
466 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
467 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
468 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
471 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
472 INTERCEPTOR_STRTO(ret_type, func, char_type) \
473 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
474 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
475 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
477 #define INTERCEPTORS_STRTO_SRET(ret_type, func, char_type) \
478 INTERCEPTOR_STRTO_SRET(ret_type, func, char_type) \
479 INTERCEPTOR_STRTO_SRET_LOC(ret_type, func##_l, char_type) \
480 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_l, char_type) \
481 INTERCEPTOR_STRTO_SRET_LOC(ret_type, __##func##_internal, char_type)
483 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
484 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
485 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
486 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
487 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
490 INTERCEPTORS_STRTO(double, strtod
, char)
491 INTERCEPTORS_STRTO(float, strtof
, char)
493 INTERCEPTORS_STRTO_SRET(long double, strtold
, char)
495 INTERCEPTORS_STRTO(long double, strtold
, char)
497 INTERCEPTORS_STRTO_BASE(long, strtol
, char)
498 INTERCEPTORS_STRTO_BASE(long long, strtoll
, char)
499 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul
, char)
500 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull
, char)
501 INTERCEPTORS_STRTO_BASE(u64
, strtouq
, char)
503 INTERCEPTORS_STRTO(double, wcstod
, wchar_t)
504 INTERCEPTORS_STRTO(float, wcstof
, wchar_t)
506 INTERCEPTORS_STRTO_SRET(long double, wcstold
, wchar_t)
508 INTERCEPTORS_STRTO(long double, wcstold
, wchar_t)
510 INTERCEPTORS_STRTO_BASE(long, wcstol
, wchar_t)
511 INTERCEPTORS_STRTO_BASE(long long, wcstoll
, wchar_t)
512 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul
, wchar_t)
513 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull
, wchar_t)
516 INTERCEPTORS_STRTO(double, __isoc23_strtod
, char)
517 INTERCEPTORS_STRTO(float, __isoc23_strtof
, char)
519 INTERCEPTORS_STRTO_SRET(long double, __isoc23_strtold
, char)
521 INTERCEPTORS_STRTO(long double, __isoc23_strtold
, char)
523 INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol
, char)
524 INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll
, char)
525 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul
, char)
526 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull
, char)
527 INTERCEPTORS_STRTO_BASE(u64
, __isoc23_strtouq
, char)
529 INTERCEPTORS_STRTO(double, __isoc23_wcstod
, wchar_t)
530 INTERCEPTORS_STRTO(float, __isoc23_wcstof
, wchar_t)
532 INTERCEPTORS_STRTO_SRET(long double, __isoc23_wcstold
, wchar_t)
534 INTERCEPTORS_STRTO(long double, __isoc23_wcstold
, wchar_t)
536 INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol
, wchar_t)
537 INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll
, wchar_t)
538 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul
, wchar_t)
539 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull
, wchar_t)
543 #define INTERCEPT_STRTO(func) \
544 INTERCEPT_FUNCTION(func); \
545 INTERCEPT_FUNCTION(func##_l);
547 #define INTERCEPT_STRTO(func) \
548 INTERCEPT_FUNCTION(func); \
549 INTERCEPT_FUNCTION(func##_l); \
550 INTERCEPT_FUNCTION(__##func##_l); \
551 INTERCEPT_FUNCTION(__##func##_internal);
553 #define INTERCEPT_STRTO_VER(func, ver) \
554 INTERCEPT_FUNCTION_VER(func, ver); \
555 INTERCEPT_FUNCTION_VER(func##_l, ver); \
556 INTERCEPT_FUNCTION_VER(__##func##_l, ver); \
557 INTERCEPT_FUNCTION_VER(__##func##_internal, ver);
561 // FIXME: support *wprintf in common format interceptors.
562 INTERCEPTOR(int, vswprintf
, void *str
, uptr size
, void *format
, va_list ap
) {
563 ENSURE_MSAN_INITED();
564 int res
= REAL(vswprintf
)(str
, size
, format
, ap
);
566 __msan_unpoison(str
, 4 * (res
+ 1));
571 INTERCEPTOR(int, swprintf
, void *str
, uptr size
, void *format
, ...) {
572 ENSURE_MSAN_INITED();
574 va_start(ap
, format
);
575 int res
= vswprintf(str
, size
, format
, ap
);
580 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
581 ENSURE_MSAN_INITED(); \
582 InterceptorScope interceptor_scope; \
583 ret_type res = REAL(func)(s, __VA_ARGS__); \
584 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
587 INTERCEPTOR(SIZE_T
, strftime
, char *s
, SIZE_T max
, const char *format
,
588 __sanitizer_tm
*tm
) {
589 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime
, s
, max
, format
, tm
);
592 INTERCEPTOR(SIZE_T
, strftime_l
, char *s
, SIZE_T max
, const char *format
,
593 __sanitizer_tm
*tm
, void *loc
) {
594 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime_l
, s
, max
, format
, tm
, loc
);
597 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
598 INTERCEPTOR(SIZE_T
, __strftime_l
, char *s
, SIZE_T max
, const char *format
,
599 __sanitizer_tm
*tm
, void *loc
) {
600 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, __strftime_l
, s
, max
, format
, tm
,
603 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
605 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
608 INTERCEPTOR(SIZE_T
, wcsftime
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
609 __sanitizer_tm
*tm
) {
610 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime
, s
, max
, format
, tm
);
613 INTERCEPTOR(SIZE_T
, wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
614 __sanitizer_tm
*tm
, void *loc
) {
615 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime_l
, s
, max
, format
, tm
,
619 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
620 INTERCEPTOR(SIZE_T
, __wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
621 __sanitizer_tm
*tm
, void *loc
) {
622 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, __wcsftime_l
, s
, max
, format
, tm
,
625 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
627 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
630 INTERCEPTOR(int, mbtowc
, wchar_t *dest
, const char *src
, SIZE_T n
) {
631 ENSURE_MSAN_INITED();
632 int res
= REAL(mbtowc
)(dest
, src
, n
);
633 if (res
!= -1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
637 INTERCEPTOR(SIZE_T
, mbrtowc
, wchar_t *dest
, const char *src
, SIZE_T n
,
639 ENSURE_MSAN_INITED();
640 SIZE_T res
= REAL(mbrtowc
)(dest
, src
, n
, ps
);
641 if (res
!= (SIZE_T
)-1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
645 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
646 INTERCEPTOR(wchar_t *, wmemcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
647 ENSURE_MSAN_INITED();
648 GET_STORE_STACK_TRACE
;
649 wchar_t *res
= REAL(wmemcpy
)(dest
, src
, n
);
650 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
654 #if !SANITIZER_NETBSD
655 INTERCEPTOR(wchar_t *, wmempcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
656 ENSURE_MSAN_INITED();
657 GET_STORE_STACK_TRACE
;
658 wchar_t *res
= REAL(wmempcpy
)(dest
, src
, n
);
659 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
662 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
664 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
667 INTERCEPTOR(wchar_t *, wmemset
, wchar_t *s
, wchar_t c
, SIZE_T n
) {
668 CHECK(MEM_IS_APP(s
));
669 ENSURE_MSAN_INITED();
670 wchar_t *res
= REAL(wmemset
)(s
, c
, n
);
671 __msan_unpoison(s
, n
* sizeof(wchar_t));
675 INTERCEPTOR(wchar_t *, wmemmove
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
676 ENSURE_MSAN_INITED();
677 GET_STORE_STACK_TRACE
;
678 wchar_t *res
= REAL(wmemmove
)(dest
, src
, n
);
679 MoveShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
683 INTERCEPTOR(int, wcscmp
, const wchar_t *s1
, const wchar_t *s2
) {
684 ENSURE_MSAN_INITED();
685 int res
= REAL(wcscmp
)(s1
, s2
);
689 INTERCEPTOR(int, gettimeofday
, void *tv
, void *tz
) {
690 ENSURE_MSAN_INITED();
691 int res
= REAL(gettimeofday
)(tv
, tz
);
693 __msan_unpoison(tv
, 16);
695 __msan_unpoison(tz
, 8);
699 #if !SANITIZER_NETBSD
700 INTERCEPTOR(char *, fcvt
, double x
, int a
, int *b
, int *c
) {
701 ENSURE_MSAN_INITED();
702 char *res
= REAL(fcvt
)(x
, a
, b
, c
);
703 __msan_unpoison(b
, sizeof(*b
));
704 __msan_unpoison(c
, sizeof(*c
));
706 __msan_unpoison(res
, internal_strlen(res
) + 1);
709 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
711 #define MSAN_MAYBE_INTERCEPT_FCVT
714 INTERCEPTOR(char *, getenv
, char *name
) {
715 if (msan_init_is_running
)
716 return REAL(getenv
)(name
);
717 ENSURE_MSAN_INITED();
718 char *res
= REAL(getenv
)(name
);
720 __msan_unpoison(res
, internal_strlen(res
) + 1);
724 extern char **environ
;
726 static void UnpoisonEnviron() {
727 char **envp
= environ
;
728 for (; *envp
; ++envp
) {
729 __msan_unpoison(envp
, sizeof(*envp
));
730 __msan_unpoison(*envp
, internal_strlen(*envp
) + 1);
732 // Trailing NULL pointer.
733 __msan_unpoison(envp
, sizeof(*envp
));
736 INTERCEPTOR(int, setenv
, const char *name
, const char *value
, int overwrite
) {
737 ENSURE_MSAN_INITED();
738 CHECK_UNPOISONED_STRING(name
, 0);
739 int res
= REAL(setenv
)(name
, value
, overwrite
);
740 if (!res
) UnpoisonEnviron();
744 INTERCEPTOR(int, putenv
, char *string
) {
745 ENSURE_MSAN_INITED();
746 int res
= REAL(putenv
)(string
);
747 if (!res
) UnpoisonEnviron();
751 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
752 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
753 INTERCEPTOR(int, fstat
, int fd
, void *buf
) {
754 ENSURE_MSAN_INITED();
755 int res
= REAL(fstat
)(fd
, buf
);
757 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
760 # define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
762 #define MSAN_MAYBE_INTERCEPT_FSTAT
765 #if SANITIZER_STAT_LINUX
766 INTERCEPTOR(int, fstat64
, int fd
, void *buf
) {
767 ENSURE_MSAN_INITED();
768 int res
= REAL(fstat64
)(fd
, buf
);
770 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
773 # define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
775 # define MSAN_MAYBE_INTERCEPT_FSTAT64
779 INTERCEPTOR(int, __fxstat
, int magic
, int fd
, void *buf
) {
780 ENSURE_MSAN_INITED();
781 int res
= REAL(__fxstat
)(magic
, fd
, buf
);
783 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
786 # define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
788 #define MSAN_MAYBE_INTERCEPT___FXSTAT
792 INTERCEPTOR(int, __fxstat64
, int magic
, int fd
, void *buf
) {
793 ENSURE_MSAN_INITED();
794 int res
= REAL(__fxstat64
)(magic
, fd
, buf
);
796 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
799 # define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
801 # define MSAN_MAYBE_INTERCEPT___FXSTAT64
804 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
805 INTERCEPTOR(int, fstatat
, int fd
, char *pathname
, void *buf
, int flags
) {
806 ENSURE_MSAN_INITED();
807 int res
= REAL(fstatat
)(fd
, pathname
, buf
, flags
);
808 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
811 # define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
813 # define MSAN_MAYBE_INTERCEPT_FSTATAT
816 #if SANITIZER_STAT_LINUX
817 INTERCEPTOR(int, fstatat64
, int fd
, char *pathname
, void *buf
, int flags
) {
818 ENSURE_MSAN_INITED();
819 int res
= REAL(fstatat64
)(fd
, pathname
, buf
, flags
);
821 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
824 # define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
826 # define MSAN_MAYBE_INTERCEPT_FSTATAT64
830 INTERCEPTOR(int, __fxstatat
, int magic
, int fd
, char *pathname
, void *buf
,
832 ENSURE_MSAN_INITED();
833 int res
= REAL(__fxstatat
)(magic
, fd
, pathname
, buf
, flags
);
834 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
837 # define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
839 # define MSAN_MAYBE_INTERCEPT___FXSTATAT
843 INTERCEPTOR(int, __fxstatat64
, int magic
, int fd
, char *pathname
, void *buf
,
845 ENSURE_MSAN_INITED();
846 int res
= REAL(__fxstatat64
)(magic
, fd
, pathname
, buf
, flags
);
847 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
850 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
852 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64
855 INTERCEPTOR(int, pipe
, int pipefd
[2]) {
856 if (msan_init_is_running
)
857 return REAL(pipe
)(pipefd
);
858 ENSURE_MSAN_INITED();
859 int res
= REAL(pipe
)(pipefd
);
861 __msan_unpoison(pipefd
, sizeof(int[2]));
865 INTERCEPTOR(int, pipe2
, int pipefd
[2], int flags
) {
866 ENSURE_MSAN_INITED();
867 int res
= REAL(pipe2
)(pipefd
, flags
);
869 __msan_unpoison(pipefd
, sizeof(int[2]));
873 INTERCEPTOR(int, socketpair
, int domain
, int type
, int protocol
, int sv
[2]) {
874 ENSURE_MSAN_INITED();
875 int res
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
877 __msan_unpoison(sv
, sizeof(int[2]));
881 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
882 INTERCEPTOR(char *, fgets_unlocked
, char *s
, int size
, void *stream
) {
883 ENSURE_MSAN_INITED();
884 char *res
= REAL(fgets_unlocked
)(s
, size
, stream
);
886 __msan_unpoison(s
, internal_strlen(s
) + 1);
889 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
891 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
894 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
895 if (msan_init_is_running) \
896 return REAL(getrlimit)(resource, rlim); \
897 ENSURE_MSAN_INITED(); \
898 int res = REAL(func)(resource, rlim); \
900 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
903 INTERCEPTOR(int, getrlimit
, int resource
, void *rlim
) {
904 INTERCEPTOR_GETRLIMIT_BODY(getrlimit
, resource
, rlim
);
907 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
908 INTERCEPTOR(int, __getrlimit
, int resource
, void *rlim
) {
909 INTERCEPTOR_GETRLIMIT_BODY(__getrlimit
, resource
, rlim
);
912 INTERCEPTOR(int, getrlimit64
, int resource
, void *rlim
) {
913 if (msan_init_is_running
) return REAL(getrlimit64
)(resource
, rlim
);
914 ENSURE_MSAN_INITED();
915 int res
= REAL(getrlimit64
)(resource
, rlim
);
916 if (!res
) __msan_unpoison(rlim
, __sanitizer::struct_rlimit64_sz
);
920 INTERCEPTOR(int, prlimit
, int pid
, int resource
, void *new_rlimit
,
922 if (msan_init_is_running
)
923 return REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
924 ENSURE_MSAN_INITED();
925 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit_sz
);
926 int res
= REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
927 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit_sz
);
931 INTERCEPTOR(int, prlimit64
, int pid
, int resource
, void *new_rlimit
,
933 if (msan_init_is_running
)
934 return REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
935 ENSURE_MSAN_INITED();
936 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit64_sz
);
937 int res
= REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
938 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit64_sz
);
942 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
943 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
944 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
945 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
947 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
948 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
949 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
950 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
953 INTERCEPTOR(int, gethostname
, char *name
, SIZE_T len
) {
954 ENSURE_MSAN_INITED();
955 int res
= REAL(gethostname
)(name
, len
);
956 if (!res
|| (res
== -1 && errno
== errno_ENAMETOOLONG
)) {
957 SIZE_T real_len
= internal_strnlen(name
, len
);
960 __msan_unpoison(name
, real_len
);
965 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
966 INTERCEPTOR(int, epoll_wait
, int epfd
, void *events
, int maxevents
,
968 ENSURE_MSAN_INITED();
969 int res
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
971 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
975 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
977 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
980 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
981 INTERCEPTOR(int, epoll_pwait
, int epfd
, void *events
, int maxevents
,
982 int timeout
, void *sigmask
) {
983 ENSURE_MSAN_INITED();
984 int res
= REAL(epoll_pwait
)(epfd
, events
, maxevents
, timeout
, sigmask
);
986 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
990 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
992 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
995 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
996 GET_MALLOC_STACK_TRACE
;
997 if (DlsymAlloc::Use())
998 return DlsymAlloc::Callocate(nmemb
, size
);
999 return msan_calloc(nmemb
, size
, &stack
);
1002 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
1003 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr
))
1004 return DlsymAlloc::Realloc(ptr
, size
);
1005 GET_MALLOC_STACK_TRACE
;
1006 return msan_realloc(ptr
, size
, &stack
);
1009 INTERCEPTOR(void *, reallocarray
, void *ptr
, SIZE_T nmemb
, SIZE_T size
) {
1010 GET_MALLOC_STACK_TRACE
;
1011 return msan_reallocarray(ptr
, nmemb
, size
, &stack
);
1014 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
1015 if (DlsymAlloc::Use())
1016 return DlsymAlloc::Allocate(size
);
1017 GET_MALLOC_STACK_TRACE
;
1018 return msan_malloc(size
, &stack
);
1021 void __msan_allocated_memory(const void *data
, uptr size
) {
1022 if (flags()->poison_in_malloc
) {
1023 GET_MALLOC_STACK_TRACE
;
1024 stack
.tag
= STACK_TRACE_TAG_POISON
;
1025 PoisonMemory(data
, size
, &stack
);
1029 void __msan_copy_shadow(void *dest
, const void *src
, uptr n
) {
1030 GET_STORE_STACK_TRACE
;
1031 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1034 void __sanitizer_dtor_callback(const void *data
, uptr size
) {
1035 if (flags()->poison_in_dtor
) {
1036 GET_MALLOC_STACK_TRACE
;
1037 stack
.tag
= STACK_TRACE_TAG_POISON
;
1038 PoisonMemory(data
, size
, &stack
);
1042 void __sanitizer_dtor_callback_fields(const void *data
, uptr size
) {
1043 if (flags()->poison_in_dtor
) {
1044 GET_MALLOC_STACK_TRACE
;
1045 stack
.tag
= STACK_TRACE_TAG_FIELDS
;
1046 PoisonMemory(data
, size
, &stack
);
1050 void __sanitizer_dtor_callback_vptr(const void *data
) {
1051 if (flags()->poison_in_dtor
) {
1052 GET_MALLOC_STACK_TRACE
;
1053 stack
.tag
= STACK_TRACE_TAG_VPTR
;
1054 PoisonMemory(data
, sizeof(void *), &stack
);
1058 template <class Mmap
>
1059 static void *mmap_interceptor(Mmap real_mmap
, void *addr
, SIZE_T length
,
1060 int prot
, int flags
, int fd
, OFF64_T offset
) {
1061 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
1062 void *end_addr
= (char *)addr
+ (rounded_length
- 1);
1063 if (addr
&& (!MEM_IS_APP(addr
) || !MEM_IS_APP(end_addr
))) {
1064 if (flags
& map_fixed
) {
1065 errno
= errno_EINVAL
;
1071 void *res
= real_mmap(addr
, length
, prot
, flags
, fd
, offset
);
1072 if (res
!= (void *)-1) {
1073 void *end_res
= (char *)res
+ (rounded_length
- 1);
1074 if (MEM_IS_APP(res
) && MEM_IS_APP(end_res
)) {
1075 __msan_unpoison(res
, rounded_length
);
1077 // Application has attempted to map more memory than is supported by
1078 // MSAN. Act as if we ran out of memory.
1079 internal_munmap(res
, length
);
1080 errno
= errno_ENOMEM
;
1087 INTERCEPTOR(int, getrusage
, int who
, void *usage
) {
1088 ENSURE_MSAN_INITED();
1089 int res
= REAL(getrusage
)(who
, usage
);
1091 __msan_unpoison(usage
, __sanitizer::struct_rusage_sz
);
1096 class SignalHandlerScope
{
1098 SignalHandlerScope() {
1099 if (MsanThread
*t
= GetCurrentThread())
1100 t
->EnterSignalHandler();
1102 ~SignalHandlerScope() {
1103 if (MsanThread
*t
= GetCurrentThread())
1104 t
->LeaveSignalHandler();
1108 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1109 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1110 // the signal handler.
1111 const int kMaxSignals
= 1024;
1112 static atomic_uintptr_t sigactions
[kMaxSignals
];
1113 static StaticSpinMutex sigactions_mu
;
1115 static void SignalHandler(int signo
) {
1116 SignalHandlerScope signal_handler_scope
;
1117 ScopedThreadLocalStateBackup stlsb
;
1120 typedef void (*signal_cb
)(int x
);
1122 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1126 static void SignalAction(int signo
, void *si
, void *uc
) {
1127 SignalHandlerScope signal_handler_scope
;
1128 ScopedThreadLocalStateBackup stlsb
;
1130 __msan_unpoison(si
, sizeof(__sanitizer_sigaction
));
1131 __msan_unpoison(uc
, ucontext_t_sz(uc
));
1133 typedef void (*sigaction_cb
)(int, void *, void *);
1135 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1137 CHECK_UNPOISONED(uc
, ucontext_t_sz(uc
));
1140 static void read_sigaction(const __sanitizer_sigaction
*act
) {
1141 CHECK_UNPOISONED(&act
->sa_flags
, sizeof(act
->sa_flags
));
1142 if (act
->sa_flags
& __sanitizer::sa_siginfo
)
1143 CHECK_UNPOISONED(&act
->sigaction
, sizeof(act
->sigaction
));
1145 CHECK_UNPOISONED(&act
->handler
, sizeof(act
->handler
));
1146 CHECK_UNPOISONED(&act
->sa_mask
, sizeof(act
->sa_mask
));
1149 extern "C" int pthread_attr_init(void *attr
);
1150 extern "C" int pthread_attr_destroy(void *attr
);
1152 static void *MsanThreadStartFunc(void *arg
) {
1153 MsanThread
*t
= (MsanThread
*)arg
;
1154 SetCurrentThread(t
);
1156 SetSigProcMask(&t
->starting_sigset_
, nullptr);
1157 return t
->ThreadStart();
1160 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
, void *(*callback
)(void*),
1162 ENSURE_MSAN_INITED(); // for GetTlsSize()
1163 __sanitizer_pthread_attr_t myattr
;
1165 pthread_attr_init(&myattr
);
1169 AdjustStackSize(attr
);
1171 MsanThread
*t
= MsanThread::Create(callback
, param
);
1172 ScopedBlockSignals
block(&t
->starting_sigset_
);
1173 int res
= REAL(pthread_create
)(th
, attr
, MsanThreadStartFunc
, t
);
1175 if (attr
== &myattr
)
1176 pthread_attr_destroy(&myattr
);
1178 __msan_unpoison(th
, __sanitizer::pthread_t_sz
);
1183 INTERCEPTOR(int, pthread_key_create
, __sanitizer_pthread_key_t
*key
,
1184 void (*dtor
)(void *value
)) {
1185 if (msan_init_is_running
) return REAL(pthread_key_create
)(key
, dtor
);
1186 ENSURE_MSAN_INITED();
1187 int res
= REAL(pthread_key_create
)(key
, dtor
);
1189 __msan_unpoison(key
, sizeof(*key
));
1193 #if SANITIZER_NETBSD
1194 INTERCEPTOR(int, __libc_thr_keycreate
, __sanitizer_pthread_key_t
*m
,
1195 void (*dtor
)(void *value
))
1196 ALIAS(WRAP(pthread_key_create
));
1199 INTERCEPTOR(int, pthread_join
, void *thread
, void **retval
) {
1200 ENSURE_MSAN_INITED();
1201 int res
= REAL(pthread_join
)(thread
, retval
);
1203 __msan_unpoison(retval
, sizeof(*retval
));
1208 INTERCEPTOR(int, pthread_tryjoin_np
, void *thread
, void **retval
) {
1209 ENSURE_MSAN_INITED();
1210 int res
= REAL(pthread_tryjoin_np
)(thread
, retval
);
1212 __msan_unpoison(retval
, sizeof(*retval
));
1216 INTERCEPTOR(int, pthread_timedjoin_np
, void *thread
, void **retval
,
1217 const struct timespec
*abstime
) {
1218 int res
= REAL(pthread_timedjoin_np
)(thread
, retval
, abstime
);
1220 __msan_unpoison(retval
, sizeof(*retval
));
1225 DEFINE_INTERNAL_PTHREAD_FUNCTIONS
1227 extern char *tzname
[2];
1229 INTERCEPTOR(void, tzset
, int fake
) {
1230 ENSURE_MSAN_INITED();
1231 InterceptorScope interceptor_scope
;
1234 __msan_unpoison(tzname
[0], internal_strlen(tzname
[0]) + 1);
1236 __msan_unpoison(tzname
[1], internal_strlen(tzname
[1]) + 1);
1240 struct MSanAtExitRecord
{
1241 void (*func
)(void *arg
);
1245 struct InterceptorContext
{
1247 Vector
<struct MSanAtExitRecord
*> AtExitStack
;
1249 InterceptorContext()
1254 alignas(64) static char interceptor_placeholder
[sizeof(InterceptorContext
)];
1255 InterceptorContext
*interceptor_ctx() {
1256 return reinterpret_cast<InterceptorContext
*>(&interceptor_placeholder
[0]);
1259 void MSanAtExitWrapper() {
1260 MSanAtExitRecord
*r
;
1262 Lock
l(&interceptor_ctx()->atexit_mu
);
1264 uptr element
= interceptor_ctx()->AtExitStack
.Size() - 1;
1265 r
= interceptor_ctx()->AtExitStack
[element
];
1266 interceptor_ctx()->AtExitStack
.PopBack();
1270 ((void(*)())r
->func
)();
1274 void MSanCxaAtExitWrapper(void *arg
) {
1276 MSanAtExitRecord
*r
= (MSanAtExitRecord
*)arg
;
1277 // libc before 2.27 had race which caused occasional double handler execution
1278 // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1285 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
);
1287 // Unpoison argument shadow for C++ module destructors.
1288 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
1290 if (msan_init_is_running
) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
1291 return setup_at_exit_wrapper((void(*)())func
, arg
, dso_handle
);
1294 // Unpoison argument shadow for C++ module destructors.
1295 INTERCEPTOR(int, atexit
, void (*func
)()) {
1296 // Avoid calling real atexit as it is unreachable on at least on Linux.
1297 if (msan_init_is_running
)
1298 return REAL(__cxa_atexit
)((void (*)(void *a
))func
, 0, 0);
1299 return setup_at_exit_wrapper((void(*)())func
, 0, 0);
1302 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
) {
1303 ENSURE_MSAN_INITED();
1304 MSanAtExitRecord
*r
=
1305 (MSanAtExitRecord
*)InternalAlloc(sizeof(MSanAtExitRecord
));
1306 r
->func
= (void(*)(void *a
))f
;
1310 // NetBSD does not preserve the 2nd argument if dso is equal to 0
1311 // Store ctx in a local stack-like structure
1313 Lock
l(&interceptor_ctx()->atexit_mu
);
1315 res
= REAL(__cxa_atexit
)((void (*)(void *a
))MSanAtExitWrapper
, 0, 0);
1317 interceptor_ctx()->AtExitStack
.PushBack(r
);
1320 res
= REAL(__cxa_atexit
)(MSanCxaAtExitWrapper
, r
, dso
);
1325 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1328 INTERCEPTOR(int, openpty
, int *aparent
, int *aworker
, char *name
,
1329 const void *termp
, const void *winp
) {
1330 ENSURE_MSAN_INITED();
1331 InterceptorScope interceptor_scope
;
1332 int res
= REAL(openpty
)(aparent
, aworker
, name
, termp
, winp
);
1334 __msan_unpoison(aparent
, sizeof(*aparent
));
1335 __msan_unpoison(aworker
, sizeof(*aworker
));
1339 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1341 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1344 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1347 INTERCEPTOR(int, forkpty
, int *aparent
, char *name
, const void *termp
,
1349 ENSURE_MSAN_INITED();
1350 InterceptorScope interceptor_scope
;
1351 int res
= REAL(forkpty
)(aparent
, name
, termp
, winp
);
1353 __msan_unpoison(aparent
, sizeof(*aparent
));
1356 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1358 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1361 struct MSanInterceptorContext
{
1362 bool in_interceptor_scope
;
1368 // FIXME: ask frontend whether we need to return failure.
1372 } // namespace __msan
1374 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1376 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1378 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1379 CHECK_UNPOISONED_0(x, n); \
1382 #define MSAN_INTERCEPT_FUNC(name) \
1384 if (!INTERCEPT_FUNCTION(name)) \
1385 VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1388 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1390 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
1391 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1394 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
1396 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
1397 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1398 #name, ver, #name); \
1401 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1402 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1403 MSAN_INTERCEPT_FUNC_VER(name, ver)
1404 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1405 MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1406 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1407 UnpoisonParam(count)
1408 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1409 __msan_unpoison(ptr, size)
1410 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1411 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1412 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1413 __msan_unpoison(ptr, size)
1414 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1415 if (msan_init_is_running) \
1416 return REAL(func)(__VA_ARGS__); \
1417 ENSURE_MSAN_INITED(); \
1418 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1419 ctx = (void *)&msan_ctx; \
1421 InterceptorScope interceptor_scope; \
1422 __msan_unpoison(__errno_location(), sizeof(int));
1423 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1426 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1429 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1432 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1435 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1437 } while (false) // FIXME
1438 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1440 } while (false) // FIXME
1441 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1442 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1443 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1445 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1446 if (filename && map) \
1447 ForEachMappedRegion(map, __msan_unpoison); \
1450 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1452 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1453 if (MsanThread *t = GetCurrentThread()) { \
1454 *begin = t->tls_begin(); \
1455 *end = t->tls_end(); \
1457 *begin = *end = 0; \
1460 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1463 return __msan_memset(block, c, size); \
1465 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1468 return __msan_memmove(to, from, size); \
1470 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1473 return __msan_memcpy(to, from, size); \
1476 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1478 GET_STORE_STACK_TRACE; \
1479 CopyShadowAndOrigin(to, from, size, &stack); \
1480 __msan_unpoison(to + size, 1); \
1483 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1486 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
1489 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1490 #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
1491 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1493 static uptr
signal_impl(int signo
, uptr cb
);
1494 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1495 __sanitizer_sigaction
*oldact
);
1497 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1498 { return sigaction_impl(signo, act, oldact); }
1500 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1502 handler = signal_impl(signo, handler); \
1503 InterceptorScope interceptor_scope; \
1504 return REAL(func)(signo, handler); \
1507 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
1509 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1511 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1512 __sanitizer_sigaction
*oldact
) {
1513 ENSURE_MSAN_INITED();
1514 if (signo
<= 0 || signo
>= kMaxSignals
) {
1515 errno
= errno_EINVAL
;
1518 if (act
) read_sigaction(act
);
1520 if (flags()->wrap_signals
) {
1521 SpinMutexLock
lock(&sigactions_mu
);
1522 uptr old_cb
= atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1523 __sanitizer_sigaction new_act
;
1524 __sanitizer_sigaction
*pnew_act
= act
? &new_act
: nullptr;
1526 REAL(memcpy
)(pnew_act
, act
, sizeof(__sanitizer_sigaction
));
1527 uptr cb
= (uptr
)pnew_act
->sigaction
;
1528 uptr new_cb
= (pnew_act
->sa_flags
& __sanitizer::sa_siginfo
)
1529 ? (uptr
)SignalAction
1530 : (uptr
)SignalHandler
;
1531 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1532 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1533 pnew_act
->sigaction
= (decltype(pnew_act
->sigaction
))new_cb
;
1536 res
= REAL(SIGACTION_SYMNAME
)(signo
, pnew_act
, oldact
);
1537 if (res
== 0 && oldact
) {
1538 uptr cb
= (uptr
)oldact
->sigaction
;
1539 if (cb
== (uptr
)SignalAction
|| cb
== (uptr
)SignalHandler
) {
1540 oldact
->sigaction
= (decltype(oldact
->sigaction
))old_cb
;
1544 res
= REAL(SIGACTION_SYMNAME
)(signo
, act
, oldact
);
1547 if (res
== 0 && oldact
) {
1548 __msan_unpoison(oldact
, sizeof(__sanitizer_sigaction
));
1553 static uptr
signal_impl(int signo
, uptr cb
) {
1554 ENSURE_MSAN_INITED();
1555 if (signo
<= 0 || signo
>= kMaxSignals
) {
1556 errno
= errno_EINVAL
;
1559 if (flags()->wrap_signals
) {
1560 SpinMutexLock
lock(&sigactions_mu
);
1561 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1562 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1563 cb
= (uptr
)&SignalHandler
;
1569 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1570 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1573 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1576 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1577 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1578 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1580 INTERCEPTOR(const char *, strsignal
, int sig
) {
1582 COMMON_INTERCEPTOR_ENTER(ctx
, strsignal
, sig
);
1583 const char *res
= REAL(strsignal
)(sig
);
1585 __msan_unpoison(res
, internal_strlen(res
) + 1);
1589 INTERCEPTOR(int, dladdr
, void *addr
, void *info
) {
1591 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr
, addr
, info
);
1592 int res
= REAL(dladdr
)(addr
, info
);
1594 UnpoisonDllAddrInfo(info
);
1599 INTERCEPTOR(int, dladdr1
, void *addr
, void *info
, void **extra_info
,
1602 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr1
, addr
, info
, extra_info
, flags
);
1603 int res
= REAL(dladdr1
)(addr
, info
, extra_info
, flags
);
1605 UnpoisonDllAddrInfo(info
);
1606 UnpoisonDllAddr1ExtraInfo(extra_info
, flags
);
1610 # define MSAN_MAYBE_INTERCEPT_DLADDR1 MSAN_INTERCEPT_FUNC(dladdr1)
1612 #define MSAN_MAYBE_INTERCEPT_DLADDR1
1615 INTERCEPTOR(char *, dlerror
, int fake
) {
1617 COMMON_INTERCEPTOR_ENTER(ctx
, dlerror
, fake
);
1618 char *res
= REAL(dlerror
)(fake
);
1620 __msan_unpoison(res
, internal_strlen(res
) + 1);
1624 typedef int (*dl_iterate_phdr_cb
)(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1626 struct dl_iterate_phdr_data
{
1627 dl_iterate_phdr_cb callback
;
1631 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1634 __msan_unpoison(info
, size
);
1635 if (info
->dlpi_phdr
&& info
->dlpi_phnum
)
1636 __msan_unpoison(info
->dlpi_phdr
, struct_ElfW_Phdr_sz
* info
->dlpi_phnum
);
1637 if (info
->dlpi_name
)
1638 __msan_unpoison(info
->dlpi_name
, internal_strlen(info
->dlpi_name
) + 1);
1640 dl_iterate_phdr_data
*cbdata
= (dl_iterate_phdr_data
*)data
;
1642 return cbdata
->callback(info
, size
, cbdata
->data
);
1645 INTERCEPTOR(void *, shmat
, int shmid
, const void *shmaddr
, int shmflg
) {
1646 ENSURE_MSAN_INITED();
1647 void *p
= REAL(shmat
)(shmid
, shmaddr
, shmflg
);
1648 if (p
!= (void *)-1) {
1649 __sanitizer_shmid_ds ds
;
1650 int res
= REAL(shmctl
)(shmid
, shmctl_ipc_stat
, &ds
);
1652 __msan_unpoison(p
, ds
.shm_segsz
);
1658 INTERCEPTOR(int, dl_iterate_phdr
, dl_iterate_phdr_cb callback
, void *data
) {
1660 COMMON_INTERCEPTOR_ENTER(ctx
, dl_iterate_phdr
, callback
, data
);
1661 dl_iterate_phdr_data cbdata
;
1662 cbdata
.callback
= callback
;
1664 int res
= REAL(dl_iterate_phdr
)(msan_dl_iterate_phdr_cb
, (void *)&cbdata
);
1668 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
1669 INTERCEPTOR(wchar_t *, wcschr
, void *s
, wchar_t wc
, void *ps
) {
1670 ENSURE_MSAN_INITED();
1671 wchar_t *res
= REAL(wcschr
)(s
, wc
, ps
);
1675 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
1676 INTERCEPTOR(wchar_t *, wcscpy
, wchar_t *dest
, const wchar_t *src
) {
1677 ENSURE_MSAN_INITED();
1678 GET_STORE_STACK_TRACE
;
1679 wchar_t *res
= REAL(wcscpy
)(dest
, src
);
1680 CopyShadowAndOrigin(dest
, src
, sizeof(wchar_t) * (internal_wcslen(src
) + 1),
1685 INTERCEPTOR(wchar_t *, wcsncpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
1686 ENSURE_MSAN_INITED();
1687 GET_STORE_STACK_TRACE
;
1688 SIZE_T copy_size
= internal_wcsnlen(src
, n
);
1689 if (copy_size
< n
) copy_size
++; // trailing \0
1690 wchar_t *res
= REAL(wcsncpy
)(dest
, src
, n
);
1691 CopyShadowAndOrigin(dest
, src
, copy_size
* sizeof(wchar_t), &stack
);
1692 __msan_unpoison(dest
+ copy_size
, (n
- copy_size
) * sizeof(wchar_t));
1696 // These interface functions reside here so that they can use
1697 // REAL(memset), etc.
1698 void __msan_unpoison(const void *a
, uptr size
) {
1699 if (!MEM_IS_APP(a
)) return;
1700 SetShadow(a
, size
, 0);
1703 void __msan_poison(const void *a
, uptr size
) {
1704 if (!MEM_IS_APP(a
)) return;
1705 SetShadow(a
, size
, __msan::flags()->poison_heap_with_zeroes
? 0 : -1);
1708 void __msan_poison_stack(void *a
, uptr size
) {
1709 if (!MEM_IS_APP(a
)) return;
1710 SetShadow(a
, size
, __msan::flags()->poison_stack_with_zeroes
? 0 : -1);
1713 void __msan_unpoison_param(uptr n
) { UnpoisonParam(n
); }
1715 void __msan_clear_and_unpoison(void *a
, uptr size
) {
1716 REAL(memset
)(a
, 0, size
);
1717 SetShadow(a
, size
, 0);
1720 void *__msan_memcpy(void *dest
, const void *src
, SIZE_T n
) {
1721 if (!msan_inited
) return internal_memcpy(dest
, src
, n
);
1722 if (msan_init_is_running
|| __msan::IsInSymbolizerOrUnwider())
1723 return REAL(memcpy
)(dest
, src
, n
);
1724 ENSURE_MSAN_INITED();
1725 GET_STORE_STACK_TRACE
;
1726 void *res
= REAL(memcpy
)(dest
, src
, n
);
1727 CopyShadowAndOrigin(dest
, src
, n
, &stack
);
1731 void *__msan_memset(void *s
, int c
, SIZE_T n
) {
1732 if (!msan_inited
) return internal_memset(s
, c
, n
);
1733 if (msan_init_is_running
) return REAL(memset
)(s
, c
, n
);
1734 ENSURE_MSAN_INITED();
1735 void *res
= REAL(memset
)(s
, c
, n
);
1736 __msan_unpoison(s
, n
);
1740 void *__msan_memmove(void *dest
, const void *src
, SIZE_T n
) {
1741 if (!msan_inited
) return internal_memmove(dest
, src
, n
);
1742 if (msan_init_is_running
) return REAL(memmove
)(dest
, src
, n
);
1743 ENSURE_MSAN_INITED();
1744 GET_STORE_STACK_TRACE
;
1745 void *res
= REAL(memmove
)(dest
, src
, n
);
1746 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1750 void __msan_unpoison_string(const char* s
) {
1751 if (!MEM_IS_APP(s
)) return;
1752 __msan_unpoison(s
, internal_strlen(s
) + 1);
1757 void InitializeInterceptors() {
1758 static int inited
= 0;
1759 CHECK_EQ(inited
, 0);
1761 __interception::DoesNotSupportStaticLinking();
1763 new(interceptor_ctx()) InterceptorContext();
1765 InitializeCommonInterceptors();
1766 InitializeSignalInterceptors();
1768 INTERCEPT_FUNCTION(posix_memalign
);
1769 MSAN_MAYBE_INTERCEPT_MEMALIGN
;
1770 MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
;
1771 INTERCEPT_FUNCTION(valloc
);
1772 MSAN_MAYBE_INTERCEPT_PVALLOC
;
1773 INTERCEPT_FUNCTION(malloc
);
1774 INTERCEPT_FUNCTION(calloc
);
1775 INTERCEPT_FUNCTION(realloc
);
1776 INTERCEPT_FUNCTION(reallocarray
);
1777 INTERCEPT_FUNCTION(free
);
1778 MSAN_MAYBE_INTERCEPT_CFREE
;
1779 MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
;
1780 MSAN_MAYBE_INTERCEPT_MALLINFO
;
1781 MSAN_MAYBE_INTERCEPT_MALLINFO2
;
1782 MSAN_MAYBE_INTERCEPT_MALLOPT
;
1783 MSAN_MAYBE_INTERCEPT_MALLOC_STATS
;
1784 INTERCEPT_FUNCTION(fread
);
1785 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
;
1786 INTERCEPT_FUNCTION(memccpy
);
1787 MSAN_MAYBE_INTERCEPT_MEMPCPY
;
1788 INTERCEPT_FUNCTION(bcopy
);
1789 INTERCEPT_FUNCTION(wmemset
);
1790 INTERCEPT_FUNCTION(wmemcpy
);
1791 MSAN_MAYBE_INTERCEPT_WMEMPCPY
;
1792 INTERCEPT_FUNCTION(wmemmove
);
1793 INTERCEPT_FUNCTION(strcpy
);
1794 MSAN_MAYBE_INTERCEPT_STPCPY
;
1795 MSAN_MAYBE_INTERCEPT_STPNCPY
;
1796 INTERCEPT_FUNCTION(strdup
);
1797 MSAN_MAYBE_INTERCEPT___STRDUP
;
1798 INTERCEPT_FUNCTION(strncpy
);
1799 MSAN_MAYBE_INTERCEPT_GCVT
;
1800 INTERCEPT_FUNCTION(strcat
);
1801 INTERCEPT_FUNCTION(strncat
);
1802 INTERCEPT_STRTO(strtod
);
1803 INTERCEPT_STRTO(strtof
);
1804 #ifdef SANITIZER_NLDBL_VERSION
1805 INTERCEPT_STRTO_VER(strtold
, SANITIZER_NLDBL_VERSION
);
1807 INTERCEPT_STRTO(strtold
);
1809 INTERCEPT_STRTO(strtol
);
1810 INTERCEPT_STRTO(strtoul
);
1811 INTERCEPT_STRTO(strtoll
);
1812 INTERCEPT_STRTO(strtoull
);
1813 INTERCEPT_STRTO(strtouq
);
1814 INTERCEPT_STRTO(wcstod
);
1815 INTERCEPT_STRTO(wcstof
);
1816 #ifdef SANITIZER_NLDBL_VERSION
1817 INTERCEPT_STRTO_VER(wcstold
, SANITIZER_NLDBL_VERSION
);
1819 INTERCEPT_STRTO(wcstold
);
1821 INTERCEPT_STRTO(wcstol
);
1822 INTERCEPT_STRTO(wcstoul
);
1823 INTERCEPT_STRTO(wcstoll
);
1824 INTERCEPT_STRTO(wcstoull
);
1826 INTERCEPT_STRTO(__isoc23_strtod
);
1827 INTERCEPT_STRTO(__isoc23_strtof
);
1828 INTERCEPT_STRTO(__isoc23_strtold
);
1829 INTERCEPT_STRTO(__isoc23_strtol
);
1830 INTERCEPT_STRTO(__isoc23_strtoul
);
1831 INTERCEPT_STRTO(__isoc23_strtoll
);
1832 INTERCEPT_STRTO(__isoc23_strtoull
);
1833 INTERCEPT_STRTO(__isoc23_strtouq
);
1834 INTERCEPT_STRTO(__isoc23_wcstod
);
1835 INTERCEPT_STRTO(__isoc23_wcstof
);
1836 INTERCEPT_STRTO(__isoc23_wcstold
);
1837 INTERCEPT_STRTO(__isoc23_wcstol
);
1838 INTERCEPT_STRTO(__isoc23_wcstoul
);
1839 INTERCEPT_STRTO(__isoc23_wcstoll
);
1840 INTERCEPT_STRTO(__isoc23_wcstoull
);
1843 #ifdef SANITIZER_NLDBL_VERSION
1844 INTERCEPT_FUNCTION_VER(vswprintf
, SANITIZER_NLDBL_VERSION
);
1845 INTERCEPT_FUNCTION_VER(swprintf
, SANITIZER_NLDBL_VERSION
);
1847 INTERCEPT_FUNCTION(vswprintf
);
1848 INTERCEPT_FUNCTION(swprintf
);
1850 INTERCEPT_FUNCTION(strftime
);
1851 INTERCEPT_FUNCTION(strftime_l
);
1852 MSAN_MAYBE_INTERCEPT___STRFTIME_L
;
1853 INTERCEPT_FUNCTION(wcsftime
);
1854 INTERCEPT_FUNCTION(wcsftime_l
);
1855 MSAN_MAYBE_INTERCEPT___WCSFTIME_L
;
1856 INTERCEPT_FUNCTION(mbtowc
);
1857 INTERCEPT_FUNCTION(mbrtowc
);
1858 INTERCEPT_FUNCTION(wcslen
);
1859 INTERCEPT_FUNCTION(wcsnlen
);
1860 INTERCEPT_FUNCTION(wcschr
);
1861 INTERCEPT_FUNCTION(wcscpy
);
1862 INTERCEPT_FUNCTION(wcsncpy
);
1863 INTERCEPT_FUNCTION(wcscmp
);
1864 INTERCEPT_FUNCTION(getenv
);
1865 INTERCEPT_FUNCTION(setenv
);
1866 INTERCEPT_FUNCTION(putenv
);
1867 INTERCEPT_FUNCTION(gettimeofday
);
1868 MSAN_MAYBE_INTERCEPT_FCVT
;
1869 MSAN_MAYBE_INTERCEPT_FSTAT
;
1870 MSAN_MAYBE_INTERCEPT_FSTAT64
;
1871 MSAN_MAYBE_INTERCEPT___FXSTAT
;
1872 MSAN_MAYBE_INTERCEPT_FSTATAT
;
1873 MSAN_MAYBE_INTERCEPT_FSTATAT64
;
1874 MSAN_MAYBE_INTERCEPT___FXSTATAT
;
1875 MSAN_MAYBE_INTERCEPT___FXSTAT64
;
1876 MSAN_MAYBE_INTERCEPT___FXSTATAT64
;
1877 INTERCEPT_FUNCTION(pipe
);
1878 INTERCEPT_FUNCTION(pipe2
);
1879 INTERCEPT_FUNCTION(socketpair
);
1880 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
;
1881 INTERCEPT_FUNCTION(getrlimit
);
1882 MSAN_MAYBE_INTERCEPT___GETRLIMIT
;
1883 MSAN_MAYBE_INTERCEPT_GETRLIMIT64
;
1884 MSAN_MAYBE_INTERCEPT_PRLIMIT
;
1885 MSAN_MAYBE_INTERCEPT_PRLIMIT64
;
1886 INTERCEPT_FUNCTION(gethostname
);
1887 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
;
1888 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
;
1889 INTERCEPT_FUNCTION(strsignal
);
1890 INTERCEPT_FUNCTION(dladdr
);
1891 MSAN_MAYBE_INTERCEPT_DLADDR1
;
1892 INTERCEPT_FUNCTION(dlerror
);
1893 INTERCEPT_FUNCTION(dl_iterate_phdr
);
1894 INTERCEPT_FUNCTION(getrusage
);
1895 #if defined(__mips__)
1896 INTERCEPT_FUNCTION_VER(pthread_create
, "GLIBC_2.2");
1898 INTERCEPT_FUNCTION(pthread_create
);
1900 INTERCEPT_FUNCTION(pthread_join
);
1901 INTERCEPT_FUNCTION(pthread_key_create
);
1903 INTERCEPT_FUNCTION(pthread_tryjoin_np
);
1904 INTERCEPT_FUNCTION(pthread_timedjoin_np
);
1907 #if SANITIZER_NETBSD
1908 INTERCEPT_FUNCTION(__libc_thr_keycreate
);
1911 INTERCEPT_FUNCTION(pthread_join
);
1912 INTERCEPT_FUNCTION(tzset
);
1913 INTERCEPT_FUNCTION(atexit
);
1914 INTERCEPT_FUNCTION(__cxa_atexit
);
1915 INTERCEPT_FUNCTION(shmat
);
1916 MSAN_MAYBE_INTERCEPT_OPENPTY
;
1917 MSAN_MAYBE_INTERCEPT_FORKPTY
;
1921 } // namespace __msan