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 #include "interception/interception.h"
19 #include "msan_chained_origin_depot.h"
20 #include "msan_origin.h"
21 #include "msan_poisoning.h"
22 #include "msan_report.h"
23 #include "msan_thread.h"
24 #include "sanitizer_common/sanitizer_allocator.h"
25 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
26 #include "sanitizer_common/sanitizer_allocator_interface.h"
27 #include "sanitizer_common/sanitizer_atomic.h"
28 #include "sanitizer_common/sanitizer_common.h"
29 #include "sanitizer_common/sanitizer_errno.h"
30 #include "sanitizer_common/sanitizer_errno_codes.h"
31 #include "sanitizer_common/sanitizer_glibc_version.h"
32 #include "sanitizer_common/sanitizer_libc.h"
33 #include "sanitizer_common/sanitizer_linux.h"
34 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
35 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
36 #include "sanitizer_common/sanitizer_stackdepot.h"
37 #include "sanitizer_common/sanitizer_tls_get_addr.h"
38 #include "sanitizer_common/sanitizer_vector.h"
41 #define fstat __fstat50
42 #define gettimeofday __gettimeofday50
43 #define getrusage __getrusage50
44 #define tzset __tzset50
48 // ACHTUNG! No other system header includes in this file.
49 // Ideally, we should get rid of stdarg.h as well.
51 using namespace __msan
;
53 using __sanitizer::memory_order
;
54 using __sanitizer::atomic_load
;
55 using __sanitizer::atomic_store
;
56 using __sanitizer::atomic_uintptr_t
;
58 DECLARE_REAL(SIZE_T
, strlen
, const char *s
)
59 DECLARE_REAL(SIZE_T
, strnlen
, const char *s
, SIZE_T maxlen
)
60 DECLARE_REAL(void *, memcpy
, void *dest
, const void *src
, uptr n
)
61 DECLARE_REAL(void *, memset
, void *dest
, int c
, uptr n
)
63 // True if this is a nested interceptor.
64 static THREADLOCAL
int in_interceptor_scope
;
66 void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope
; }
67 void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope
; }
69 struct InterceptorScope
{
70 InterceptorScope() { ++in_interceptor_scope
; }
71 ~InterceptorScope() { --in_interceptor_scope
; }
74 bool IsInInterceptorScope() {
75 return in_interceptor_scope
;
78 struct DlsymAlloc
: public DlSymAllocator
<DlsymAlloc
> {
79 static bool UseImpl() { return !msan_inited
; }
82 #define ENSURE_MSAN_INITED() do { \
83 CHECK(!msan_init_is_running); \
89 // Check that [x, x+n) range is unpoisoned.
90 #define CHECK_UNPOISONED_0(x, n) \
92 sptr __offset = __msan_test_shadow(x, n); \
93 if (__msan::IsInSymbolizerOrUnwider()) \
95 if (__offset >= 0 && __msan::flags()->report_umrs) { \
97 ReportUMRInsideAddressRange(__func__, x, n, __offset); \
98 __msan::PrintWarningWithOrigin( \
99 pc, bp, __msan_get_origin((const char *)x + __offset)); \
100 if (__msan::flags()->halt_on_error) { \
101 Printf("Exiting\n"); \
107 // Check that [x, x+n) range is unpoisoned unless we are in a nested
109 #define CHECK_UNPOISONED(x, n) \
111 if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
114 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
115 CHECK_UNPOISONED((x), \
116 common_flags()->strict_string_checks ? (len) + 1 : (n) )
118 #define CHECK_UNPOISONED_STRING(x, n) \
119 CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
121 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
122 INTERCEPTOR(SIZE_T
, fread_unlocked
, void *ptr
, SIZE_T size
, SIZE_T nmemb
,
124 ENSURE_MSAN_INITED();
125 SIZE_T res
= REAL(fread_unlocked
)(ptr
, size
, nmemb
, file
);
127 __msan_unpoison(ptr
, res
*size
);
130 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
132 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
135 #if !SANITIZER_NETBSD
136 INTERCEPTOR(void *, mempcpy
, void *dest
, const void *src
, SIZE_T n
) {
137 return (char *)__msan_memcpy(dest
, src
, n
) + n
;
139 #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
141 #define MSAN_MAYBE_INTERCEPT_MEMPCPY
144 INTERCEPTOR(void *, memccpy
, void *dest
, const void *src
, int c
, SIZE_T n
) {
145 ENSURE_MSAN_INITED();
146 void *res
= REAL(memccpy
)(dest
, src
, c
, n
);
147 CHECK(!res
|| (res
>= dest
&& res
<= (char *)dest
+ n
));
148 SIZE_T sz
= res
? (char *)res
- (char *)dest
: n
;
149 CHECK_UNPOISONED(src
, sz
);
150 __msan_unpoison(dest
, sz
);
154 INTERCEPTOR(void *, bcopy
, const void *src
, void *dest
, SIZE_T n
) {
155 return __msan_memmove(dest
, src
, n
);
158 INTERCEPTOR(int, posix_memalign
, void **memptr
, SIZE_T alignment
, SIZE_T size
) {
159 GET_MALLOC_STACK_TRACE
;
161 int res
= msan_posix_memalign(memptr
, alignment
, size
, &stack
);
163 __msan_unpoison(memptr
, sizeof(*memptr
));
167 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
168 INTERCEPTOR(void *, memalign
, SIZE_T alignment
, SIZE_T size
) {
169 GET_MALLOC_STACK_TRACE
;
170 return msan_memalign(alignment
, size
, &stack
);
172 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
174 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
177 INTERCEPTOR(void *, aligned_alloc
, SIZE_T alignment
, SIZE_T size
) {
178 GET_MALLOC_STACK_TRACE
;
179 return msan_aligned_alloc(alignment
, size
, &stack
);
182 #if !SANITIZER_NETBSD
183 INTERCEPTOR(void *, __libc_memalign
, SIZE_T alignment
, SIZE_T size
) {
184 GET_MALLOC_STACK_TRACE
;
185 void *ptr
= msan_memalign(alignment
, size
, &stack
);
187 DTLS_on_libc_memalign(ptr
, size
);
190 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
192 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
195 INTERCEPTOR(void *, valloc
, SIZE_T size
) {
196 GET_MALLOC_STACK_TRACE
;
197 return msan_valloc(size
, &stack
);
200 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
201 INTERCEPTOR(void *, pvalloc
, SIZE_T size
) {
202 GET_MALLOC_STACK_TRACE
;
203 return msan_pvalloc(size
, &stack
);
205 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
207 #define MSAN_MAYBE_INTERCEPT_PVALLOC
210 INTERCEPTOR(void, free
, void *ptr
) {
213 if (DlsymAlloc::PointerIsMine(ptr
))
214 return DlsymAlloc::Free(ptr
);
215 GET_MALLOC_STACK_TRACE
;
216 MsanDeallocate(&stack
, ptr
);
219 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
220 INTERCEPTOR(void, cfree
, void *ptr
) {
223 if (DlsymAlloc::PointerIsMine(ptr
))
224 return DlsymAlloc::Free(ptr
);
225 GET_MALLOC_STACK_TRACE
;
226 MsanDeallocate(&stack
, ptr
);
228 # define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
230 #define MSAN_MAYBE_INTERCEPT_CFREE
233 #if !SANITIZER_NETBSD
234 INTERCEPTOR(uptr
, malloc_usable_size
, void *ptr
) {
235 return __sanitizer_get_allocated_size(ptr
);
237 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
238 INTERCEPT_FUNCTION(malloc_usable_size)
240 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
243 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
244 // This function actually returns a struct by value, but we can't unpoison a
245 // temporary! The following is equivalent on all supported platforms but
246 // aarch64 (which uses a different register for sret value). We have a test
248 INTERCEPTOR(void, mallinfo
, __sanitizer_struct_mallinfo
*sret
) {
251 asm volatile("mov %0,x8" : "=r" (r8
));
252 sret
= reinterpret_cast<__sanitizer_struct_mallinfo
*>(r8
);
254 REAL(memset
)(sret
, 0, sizeof(*sret
));
255 __msan_unpoison(sret
, sizeof(*sret
));
257 #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
259 #define MSAN_MAYBE_INTERCEPT_MALLINFO
262 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
263 INTERCEPTOR(int, mallopt
, int cmd
, int value
) {
266 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
268 #define MSAN_MAYBE_INTERCEPT_MALLOPT
271 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
272 INTERCEPTOR(void, malloc_stats
, void) {
273 // FIXME: implement, but don't call REAL(malloc_stats)!
275 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
277 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
280 INTERCEPTOR(char *, strcpy
, char *dest
, const char *src
) {
281 ENSURE_MSAN_INITED();
282 GET_STORE_STACK_TRACE
;
283 SIZE_T n
= internal_strlen(src
);
284 CHECK_UNPOISONED_STRING(src
+ n
, 0);
285 char *res
= REAL(strcpy
)(dest
, src
);
286 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
290 INTERCEPTOR(char *, strncpy
, char *dest
, const char *src
, SIZE_T n
) {
291 ENSURE_MSAN_INITED();
292 GET_STORE_STACK_TRACE
;
293 SIZE_T copy_size
= internal_strnlen(src
, n
);
295 copy_size
++; // trailing \0
296 char *res
= REAL(strncpy
)(dest
, src
, n
);
297 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
298 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
302 #if !SANITIZER_NETBSD
303 INTERCEPTOR(char *, stpcpy
, char *dest
, const char *src
) {
304 ENSURE_MSAN_INITED();
305 GET_STORE_STACK_TRACE
;
306 SIZE_T n
= internal_strlen(src
);
307 CHECK_UNPOISONED_STRING(src
+ n
, 0);
308 char *res
= REAL(stpcpy
)(dest
, src
);
309 CopyShadowAndOrigin(dest
, src
, n
+ 1, &stack
);
313 INTERCEPTOR(char *, stpncpy
, char *dest
, const char *src
, SIZE_T n
) {
314 ENSURE_MSAN_INITED();
315 GET_STORE_STACK_TRACE
;
316 SIZE_T copy_size
= Min(n
, internal_strnlen(src
, n
) + 1);
317 char *res
= REAL(stpncpy
)(dest
, src
, n
);
318 CopyShadowAndOrigin(dest
, src
, copy_size
, &stack
);
319 __msan_unpoison(dest
+ copy_size
, n
- copy_size
);
322 # define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
323 # define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
325 #define MSAN_MAYBE_INTERCEPT_STPCPY
326 # define MSAN_MAYBE_INTERCEPT_STPNCPY
329 INTERCEPTOR(char *, strdup
, char *src
) {
330 ENSURE_MSAN_INITED();
331 GET_STORE_STACK_TRACE
;
332 // On FreeBSD strdup() leverages strlen().
333 InterceptorScope interceptor_scope
;
334 SIZE_T n
= internal_strlen(src
);
335 CHECK_UNPOISONED_STRING(src
+ n
, 0);
336 char *res
= REAL(strdup
)(src
);
337 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
341 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
342 INTERCEPTOR(char *, __strdup
, char *src
) {
343 ENSURE_MSAN_INITED();
344 GET_STORE_STACK_TRACE
;
345 SIZE_T n
= internal_strlen(src
);
346 CHECK_UNPOISONED_STRING(src
+ n
, 0);
347 char *res
= REAL(__strdup
)(src
);
348 CopyShadowAndOrigin(res
, src
, n
+ 1, &stack
);
351 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
353 #define MSAN_MAYBE_INTERCEPT___STRDUP
356 #if !SANITIZER_NETBSD
357 INTERCEPTOR(char *, gcvt
, double number
, SIZE_T ndigit
, char *buf
) {
358 ENSURE_MSAN_INITED();
359 char *res
= REAL(gcvt
)(number
, ndigit
, buf
);
360 SIZE_T n
= internal_strlen(buf
);
361 __msan_unpoison(buf
, n
+ 1);
364 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
366 #define MSAN_MAYBE_INTERCEPT_GCVT
369 INTERCEPTOR(char *, strcat
, char *dest
, const char *src
) {
370 ENSURE_MSAN_INITED();
371 GET_STORE_STACK_TRACE
;
372 SIZE_T src_size
= internal_strlen(src
);
373 SIZE_T dest_size
= internal_strlen(dest
);
374 CHECK_UNPOISONED_STRING(src
+ src_size
, 0);
375 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
376 char *res
= REAL(strcat
)(dest
, src
);
377 CopyShadowAndOrigin(dest
+ dest_size
, src
, src_size
+ 1, &stack
);
381 INTERCEPTOR(char *, strncat
, char *dest
, const char *src
, SIZE_T n
) {
382 ENSURE_MSAN_INITED();
383 GET_STORE_STACK_TRACE
;
384 SIZE_T dest_size
= internal_strlen(dest
);
385 SIZE_T copy_size
= internal_strnlen(src
, n
);
386 CHECK_UNPOISONED_STRING(dest
+ dest_size
, 0);
387 char *res
= REAL(strncat
)(dest
, src
, n
);
388 CopyShadowAndOrigin(dest
+ dest_size
, src
, copy_size
, &stack
);
389 __msan_unpoison(dest
+ dest_size
+ copy_size
, 1); // \0
393 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
394 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
395 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
396 ENSURE_MSAN_INITED(); \
397 ret_type res = REAL(func)(__VA_ARGS__); \
398 __msan_unpoison(endptr, sizeof(*endptr)); \
401 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
402 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
403 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
406 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
407 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
409 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
412 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
413 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
415 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
418 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
419 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
420 int base, void *loc) { \
421 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
425 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
426 INTERCEPTOR_STRTO(ret_type, func, char_type) \
427 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
429 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
430 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
431 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
434 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
435 INTERCEPTOR_STRTO(ret_type, func, char_type) \
436 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
437 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
438 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
440 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
441 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
442 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
443 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
444 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
447 INTERCEPTORS_STRTO(double, strtod
, char)
448 INTERCEPTORS_STRTO(float, strtof
, char)
449 INTERCEPTORS_STRTO(long double, strtold
, char)
450 INTERCEPTORS_STRTO_BASE(long, strtol
, char)
451 INTERCEPTORS_STRTO_BASE(long long, strtoll
, char)
452 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul
, char)
453 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull
, char)
454 INTERCEPTORS_STRTO_BASE(u64
, strtouq
, char)
456 INTERCEPTORS_STRTO(double, wcstod
, wchar_t)
457 INTERCEPTORS_STRTO(float, wcstof
, wchar_t)
458 INTERCEPTORS_STRTO(long double, wcstold
, wchar_t)
459 INTERCEPTORS_STRTO_BASE(long, wcstol
, wchar_t)
460 INTERCEPTORS_STRTO_BASE(long long, wcstoll
, wchar_t)
461 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul
, wchar_t)
462 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull
, wchar_t)
465 #define INTERCEPT_STRTO(func) \
466 INTERCEPT_FUNCTION(func); \
467 INTERCEPT_FUNCTION(func##_l);
469 #define INTERCEPT_STRTO(func) \
470 INTERCEPT_FUNCTION(func); \
471 INTERCEPT_FUNCTION(func##_l); \
472 INTERCEPT_FUNCTION(__##func##_l); \
473 INTERCEPT_FUNCTION(__##func##_internal);
477 // FIXME: support *wprintf in common format interceptors.
478 INTERCEPTOR(int, vswprintf
, void *str
, uptr size
, void *format
, va_list ap
) {
479 ENSURE_MSAN_INITED();
480 int res
= REAL(vswprintf
)(str
, size
, format
, ap
);
482 __msan_unpoison(str
, 4 * (res
+ 1));
487 INTERCEPTOR(int, swprintf
, void *str
, uptr size
, void *format
, ...) {
488 ENSURE_MSAN_INITED();
490 va_start(ap
, format
);
491 int res
= vswprintf(str
, size
, format
, ap
);
496 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
497 ENSURE_MSAN_INITED(); \
498 InterceptorScope interceptor_scope; \
499 ret_type res = REAL(func)(s, __VA_ARGS__); \
500 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
503 INTERCEPTOR(SIZE_T
, strftime
, char *s
, SIZE_T max
, const char *format
,
504 __sanitizer_tm
*tm
) {
505 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime
, s
, max
, format
, tm
);
508 INTERCEPTOR(SIZE_T
, strftime_l
, char *s
, SIZE_T max
, const char *format
,
509 __sanitizer_tm
*tm
, void *loc
) {
510 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, strftime_l
, s
, max
, format
, tm
, loc
);
513 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
514 INTERCEPTOR(SIZE_T
, __strftime_l
, char *s
, SIZE_T max
, const char *format
,
515 __sanitizer_tm
*tm
, void *loc
) {
516 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T
, __strftime_l
, s
, max
, format
, tm
,
519 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
521 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
524 INTERCEPTOR(SIZE_T
, wcsftime
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
525 __sanitizer_tm
*tm
) {
526 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime
, s
, max
, format
, tm
);
529 INTERCEPTOR(SIZE_T
, wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
530 __sanitizer_tm
*tm
, void *loc
) {
531 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, wcsftime_l
, s
, max
, format
, tm
,
535 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
536 INTERCEPTOR(SIZE_T
, __wcsftime_l
, wchar_t *s
, SIZE_T max
, const wchar_t *format
,
537 __sanitizer_tm
*tm
, void *loc
) {
538 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T
, __wcsftime_l
, s
, max
, format
, tm
,
541 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
543 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
546 INTERCEPTOR(int, mbtowc
, wchar_t *dest
, const char *src
, SIZE_T n
) {
547 ENSURE_MSAN_INITED();
548 int res
= REAL(mbtowc
)(dest
, src
, n
);
549 if (res
!= -1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
553 INTERCEPTOR(SIZE_T
, mbrtowc
, wchar_t *dest
, const char *src
, SIZE_T n
,
555 ENSURE_MSAN_INITED();
556 SIZE_T res
= REAL(mbrtowc
)(dest
, src
, n
, ps
);
557 if (res
!= (SIZE_T
)-1 && dest
) __msan_unpoison(dest
, sizeof(wchar_t));
561 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
562 INTERCEPTOR(wchar_t *, wmemcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
563 ENSURE_MSAN_INITED();
564 GET_STORE_STACK_TRACE
;
565 wchar_t *res
= REAL(wmemcpy
)(dest
, src
, n
);
566 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
570 #if !SANITIZER_NETBSD
571 INTERCEPTOR(wchar_t *, wmempcpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
572 ENSURE_MSAN_INITED();
573 GET_STORE_STACK_TRACE
;
574 wchar_t *res
= REAL(wmempcpy
)(dest
, src
, n
);
575 CopyShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
578 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
580 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
583 INTERCEPTOR(wchar_t *, wmemset
, wchar_t *s
, wchar_t c
, SIZE_T n
) {
584 CHECK(MEM_IS_APP(s
));
585 ENSURE_MSAN_INITED();
586 wchar_t *res
= REAL(wmemset
)(s
, c
, n
);
587 __msan_unpoison(s
, n
* sizeof(wchar_t));
591 INTERCEPTOR(wchar_t *, wmemmove
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
592 ENSURE_MSAN_INITED();
593 GET_STORE_STACK_TRACE
;
594 wchar_t *res
= REAL(wmemmove
)(dest
, src
, n
);
595 MoveShadowAndOrigin(dest
, src
, n
* sizeof(wchar_t), &stack
);
599 INTERCEPTOR(int, wcscmp
, const wchar_t *s1
, const wchar_t *s2
) {
600 ENSURE_MSAN_INITED();
601 int res
= REAL(wcscmp
)(s1
, s2
);
605 INTERCEPTOR(int, gettimeofday
, void *tv
, void *tz
) {
606 ENSURE_MSAN_INITED();
607 int res
= REAL(gettimeofday
)(tv
, tz
);
609 __msan_unpoison(tv
, 16);
611 __msan_unpoison(tz
, 8);
615 #if !SANITIZER_NETBSD
616 INTERCEPTOR(char *, fcvt
, double x
, int a
, int *b
, int *c
) {
617 ENSURE_MSAN_INITED();
618 char *res
= REAL(fcvt
)(x
, a
, b
, c
);
619 __msan_unpoison(b
, sizeof(*b
));
620 __msan_unpoison(c
, sizeof(*c
));
622 __msan_unpoison(res
, internal_strlen(res
) + 1);
625 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
627 #define MSAN_MAYBE_INTERCEPT_FCVT
630 INTERCEPTOR(char *, getenv
, char *name
) {
631 if (msan_init_is_running
)
632 return REAL(getenv
)(name
);
633 ENSURE_MSAN_INITED();
634 char *res
= REAL(getenv
)(name
);
636 __msan_unpoison(res
, internal_strlen(res
) + 1);
640 extern char **environ
;
642 static void UnpoisonEnviron() {
643 char **envp
= environ
;
644 for (; *envp
; ++envp
) {
645 __msan_unpoison(envp
, sizeof(*envp
));
646 __msan_unpoison(*envp
, internal_strlen(*envp
) + 1);
648 // Trailing NULL pointer.
649 __msan_unpoison(envp
, sizeof(*envp
));
652 INTERCEPTOR(int, setenv
, const char *name
, const char *value
, int overwrite
) {
653 ENSURE_MSAN_INITED();
654 CHECK_UNPOISONED_STRING(name
, 0);
655 int res
= REAL(setenv
)(name
, value
, overwrite
);
656 if (!res
) UnpoisonEnviron();
660 INTERCEPTOR(int, putenv
, char *string
) {
661 ENSURE_MSAN_INITED();
662 int res
= REAL(putenv
)(string
);
663 if (!res
) UnpoisonEnviron();
667 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
668 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
669 INTERCEPTOR(int, fstat
, int fd
, void *buf
) {
670 ENSURE_MSAN_INITED();
671 int res
= REAL(fstat
)(fd
, buf
);
673 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
676 # define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
678 #define MSAN_MAYBE_INTERCEPT_FSTAT
681 #if SANITIZER_STAT_LINUX
682 INTERCEPTOR(int, fstat64
, int fd
, void *buf
) {
683 ENSURE_MSAN_INITED();
684 int res
= REAL(fstat64
)(fd
, buf
);
686 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
689 # define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
691 # define MSAN_MAYBE_INTERCEPT_FSTAT64
695 INTERCEPTOR(int, __fxstat
, int magic
, int fd
, void *buf
) {
696 ENSURE_MSAN_INITED();
697 int res
= REAL(__fxstat
)(magic
, fd
, buf
);
699 __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
702 # define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
704 #define MSAN_MAYBE_INTERCEPT___FXSTAT
708 INTERCEPTOR(int, __fxstat64
, int magic
, int fd
, void *buf
) {
709 ENSURE_MSAN_INITED();
710 int res
= REAL(__fxstat64
)(magic
, fd
, buf
);
712 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
715 # define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
717 # define MSAN_MAYBE_INTERCEPT___FXSTAT64
720 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
721 INTERCEPTOR(int, fstatat
, int fd
, char *pathname
, void *buf
, int flags
) {
722 ENSURE_MSAN_INITED();
723 int res
= REAL(fstatat
)(fd
, pathname
, buf
, flags
);
724 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
727 # define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
729 # define MSAN_MAYBE_INTERCEPT_FSTATAT
732 #if SANITIZER_STAT_LINUX
733 INTERCEPTOR(int, fstatat64
, int fd
, char *pathname
, void *buf
, int flags
) {
734 ENSURE_MSAN_INITED();
735 int res
= REAL(fstatat64
)(fd
, pathname
, buf
, flags
);
737 __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
740 # define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
742 # define MSAN_MAYBE_INTERCEPT_FSTATAT64
746 INTERCEPTOR(int, __fxstatat
, int magic
, int fd
, char *pathname
, void *buf
,
748 ENSURE_MSAN_INITED();
749 int res
= REAL(__fxstatat
)(magic
, fd
, pathname
, buf
, flags
);
750 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat_sz
);
753 # define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
755 # define MSAN_MAYBE_INTERCEPT___FXSTATAT
759 INTERCEPTOR(int, __fxstatat64
, int magic
, int fd
, char *pathname
, void *buf
,
761 ENSURE_MSAN_INITED();
762 int res
= REAL(__fxstatat64
)(magic
, fd
, pathname
, buf
, flags
);
763 if (!res
) __msan_unpoison(buf
, __sanitizer::struct_stat64_sz
);
766 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
768 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64
771 INTERCEPTOR(int, pipe
, int pipefd
[2]) {
772 if (msan_init_is_running
)
773 return REAL(pipe
)(pipefd
);
774 ENSURE_MSAN_INITED();
775 int res
= REAL(pipe
)(pipefd
);
777 __msan_unpoison(pipefd
, sizeof(int[2]));
781 INTERCEPTOR(int, pipe2
, int pipefd
[2], int flags
) {
782 ENSURE_MSAN_INITED();
783 int res
= REAL(pipe2
)(pipefd
, flags
);
785 __msan_unpoison(pipefd
, sizeof(int[2]));
789 INTERCEPTOR(int, socketpair
, int domain
, int type
, int protocol
, int sv
[2]) {
790 ENSURE_MSAN_INITED();
791 int res
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
793 __msan_unpoison(sv
, sizeof(int[2]));
797 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
798 INTERCEPTOR(char *, fgets_unlocked
, char *s
, int size
, void *stream
) {
799 ENSURE_MSAN_INITED();
800 char *res
= REAL(fgets_unlocked
)(s
, size
, stream
);
802 __msan_unpoison(s
, internal_strlen(s
) + 1);
805 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
807 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
810 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
811 if (msan_init_is_running) \
812 return REAL(getrlimit)(resource, rlim); \
813 ENSURE_MSAN_INITED(); \
814 int res = REAL(func)(resource, rlim); \
816 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
819 INTERCEPTOR(int, getrlimit
, int resource
, void *rlim
) {
820 INTERCEPTOR_GETRLIMIT_BODY(getrlimit
, resource
, rlim
);
823 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
824 INTERCEPTOR(int, __getrlimit
, int resource
, void *rlim
) {
825 INTERCEPTOR_GETRLIMIT_BODY(__getrlimit
, resource
, rlim
);
828 INTERCEPTOR(int, getrlimit64
, int resource
, void *rlim
) {
829 if (msan_init_is_running
) return REAL(getrlimit64
)(resource
, rlim
);
830 ENSURE_MSAN_INITED();
831 int res
= REAL(getrlimit64
)(resource
, rlim
);
832 if (!res
) __msan_unpoison(rlim
, __sanitizer::struct_rlimit64_sz
);
836 INTERCEPTOR(int, prlimit
, int pid
, int resource
, void *new_rlimit
,
838 if (msan_init_is_running
)
839 return REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
840 ENSURE_MSAN_INITED();
841 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit_sz
);
842 int res
= REAL(prlimit
)(pid
, resource
, new_rlimit
, old_rlimit
);
843 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit_sz
);
847 INTERCEPTOR(int, prlimit64
, int pid
, int resource
, void *new_rlimit
,
849 if (msan_init_is_running
)
850 return REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
851 ENSURE_MSAN_INITED();
852 CHECK_UNPOISONED(new_rlimit
, __sanitizer::struct_rlimit64_sz
);
853 int res
= REAL(prlimit64
)(pid
, resource
, new_rlimit
, old_rlimit
);
854 if (!res
) __msan_unpoison(old_rlimit
, __sanitizer::struct_rlimit64_sz
);
858 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
859 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
860 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
861 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
863 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
864 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
865 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
866 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
869 INTERCEPTOR(int, gethostname
, char *name
, SIZE_T len
) {
870 ENSURE_MSAN_INITED();
871 int res
= REAL(gethostname
)(name
, len
);
872 if (!res
|| (res
== -1 && errno
== errno_ENAMETOOLONG
)) {
873 SIZE_T real_len
= internal_strnlen(name
, len
);
876 __msan_unpoison(name
, real_len
);
881 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
882 INTERCEPTOR(int, epoll_wait
, int epfd
, void *events
, int maxevents
,
884 ENSURE_MSAN_INITED();
885 int res
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
887 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
891 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
893 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
896 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
897 INTERCEPTOR(int, epoll_pwait
, int epfd
, void *events
, int maxevents
,
898 int timeout
, void *sigmask
) {
899 ENSURE_MSAN_INITED();
900 int res
= REAL(epoll_pwait
)(epfd
, events
, maxevents
, timeout
, sigmask
);
902 __msan_unpoison(events
, __sanitizer::struct_epoll_event_sz
* res
);
906 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
908 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
911 INTERCEPTOR(void *, calloc
, SIZE_T nmemb
, SIZE_T size
) {
912 GET_MALLOC_STACK_TRACE
;
913 if (DlsymAlloc::Use())
914 return DlsymAlloc::Callocate(nmemb
, size
);
915 return msan_calloc(nmemb
, size
, &stack
);
918 INTERCEPTOR(void *, realloc
, void *ptr
, SIZE_T size
) {
919 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr
))
920 return DlsymAlloc::Realloc(ptr
, size
);
921 GET_MALLOC_STACK_TRACE
;
922 return msan_realloc(ptr
, size
, &stack
);
925 INTERCEPTOR(void *, reallocarray
, void *ptr
, SIZE_T nmemb
, SIZE_T size
) {
926 GET_MALLOC_STACK_TRACE
;
927 return msan_reallocarray(ptr
, nmemb
, size
, &stack
);
930 INTERCEPTOR(void *, malloc
, SIZE_T size
) {
931 if (DlsymAlloc::Use())
932 return DlsymAlloc::Allocate(size
);
933 GET_MALLOC_STACK_TRACE
;
934 return msan_malloc(size
, &stack
);
937 void __msan_allocated_memory(const void *data
, uptr size
) {
938 if (flags()->poison_in_malloc
) {
939 GET_MALLOC_STACK_TRACE
;
940 stack
.tag
= STACK_TRACE_TAG_POISON
;
941 PoisonMemory(data
, size
, &stack
);
945 void __msan_copy_shadow(void *dest
, const void *src
, uptr n
) {
946 GET_STORE_STACK_TRACE
;
947 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
950 void __sanitizer_dtor_callback(const void *data
, uptr size
) {
951 if (flags()->poison_in_dtor
) {
952 GET_MALLOC_STACK_TRACE
;
953 stack
.tag
= STACK_TRACE_TAG_POISON
;
954 PoisonMemory(data
, size
, &stack
);
958 void __sanitizer_dtor_callback_fields(const void *data
, uptr size
) {
959 if (flags()->poison_in_dtor
) {
960 GET_MALLOC_STACK_TRACE
;
961 stack
.tag
= STACK_TRACE_TAG_FIELDS
;
962 PoisonMemory(data
, size
, &stack
);
966 void __sanitizer_dtor_callback_vptr(const void *data
) {
967 if (flags()->poison_in_dtor
) {
968 GET_MALLOC_STACK_TRACE
;
969 stack
.tag
= STACK_TRACE_TAG_VPTR
;
970 PoisonMemory(data
, sizeof(void *), &stack
);
974 template <class Mmap
>
975 static void *mmap_interceptor(Mmap real_mmap
, void *addr
, SIZE_T length
,
976 int prot
, int flags
, int fd
, OFF64_T offset
) {
977 SIZE_T rounded_length
= RoundUpTo(length
, GetPageSize());
978 void *end_addr
= (char *)addr
+ (rounded_length
- 1);
979 if (addr
&& (!MEM_IS_APP(addr
) || !MEM_IS_APP(end_addr
))) {
980 if (flags
& map_fixed
) {
981 errno
= errno_EINVAL
;
987 void *res
= real_mmap(addr
, length
, prot
, flags
, fd
, offset
);
988 if (res
!= (void *)-1) {
989 void *end_res
= (char *)res
+ (rounded_length
- 1);
990 if (MEM_IS_APP(res
) && MEM_IS_APP(end_res
)) {
991 __msan_unpoison(res
, rounded_length
);
993 // Application has attempted to map more memory than is supported by
994 // MSAN. Act as if we ran out of memory.
995 internal_munmap(res
, length
);
996 errno
= errno_ENOMEM
;
1003 INTERCEPTOR(int, getrusage
, int who
, void *usage
) {
1004 ENSURE_MSAN_INITED();
1005 int res
= REAL(getrusage
)(who
, usage
);
1007 __msan_unpoison(usage
, __sanitizer::struct_rusage_sz
);
1012 class SignalHandlerScope
{
1014 SignalHandlerScope() {
1015 if (MsanThread
*t
= GetCurrentThread())
1016 t
->EnterSignalHandler();
1018 ~SignalHandlerScope() {
1019 if (MsanThread
*t
= GetCurrentThread())
1020 t
->LeaveSignalHandler();
1024 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1025 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1026 // the signal handler.
1027 const int kMaxSignals
= 1024;
1028 static atomic_uintptr_t sigactions
[kMaxSignals
];
1029 static StaticSpinMutex sigactions_mu
;
1031 static void SignalHandler(int signo
) {
1032 SignalHandlerScope signal_handler_scope
;
1033 ScopedThreadLocalStateBackup stlsb
;
1036 typedef void (*signal_cb
)(int x
);
1038 (signal_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1042 static void SignalAction(int signo
, void *si
, void *uc
) {
1043 SignalHandlerScope signal_handler_scope
;
1044 ScopedThreadLocalStateBackup stlsb
;
1046 __msan_unpoison(si
, sizeof(__sanitizer_sigaction
));
1047 __msan_unpoison(uc
, ucontext_t_sz(uc
));
1049 typedef void (*sigaction_cb
)(int, void *, void *);
1051 (sigaction_cb
)atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1053 CHECK_UNPOISONED(uc
, ucontext_t_sz(uc
));
1056 static void read_sigaction(const __sanitizer_sigaction
*act
) {
1057 CHECK_UNPOISONED(&act
->sa_flags
, sizeof(act
->sa_flags
));
1058 if (act
->sa_flags
& __sanitizer::sa_siginfo
)
1059 CHECK_UNPOISONED(&act
->sigaction
, sizeof(act
->sigaction
));
1061 CHECK_UNPOISONED(&act
->handler
, sizeof(act
->handler
));
1062 CHECK_UNPOISONED(&act
->sa_mask
, sizeof(act
->sa_mask
));
1065 extern "C" int pthread_attr_init(void *attr
);
1066 extern "C" int pthread_attr_destroy(void *attr
);
1068 static void *MsanThreadStartFunc(void *arg
) {
1069 MsanThread
*t
= (MsanThread
*)arg
;
1070 SetCurrentThread(t
);
1072 SetSigProcMask(&t
->starting_sigset_
, nullptr);
1073 return t
->ThreadStart();
1076 INTERCEPTOR(int, pthread_create
, void *th
, void *attr
, void *(*callback
)(void*),
1078 ENSURE_MSAN_INITED(); // for GetTlsSize()
1079 __sanitizer_pthread_attr_t myattr
;
1081 pthread_attr_init(&myattr
);
1085 AdjustStackSize(attr
);
1087 MsanThread
*t
= MsanThread::Create(callback
, param
);
1088 ScopedBlockSignals
block(&t
->starting_sigset_
);
1089 int res
= REAL(pthread_create
)(th
, attr
, MsanThreadStartFunc
, t
);
1091 if (attr
== &myattr
)
1092 pthread_attr_destroy(&myattr
);
1094 __msan_unpoison(th
, __sanitizer::pthread_t_sz
);
1099 INTERCEPTOR(int, pthread_key_create
, __sanitizer_pthread_key_t
*key
,
1100 void (*dtor
)(void *value
)) {
1101 if (msan_init_is_running
) return REAL(pthread_key_create
)(key
, dtor
);
1102 ENSURE_MSAN_INITED();
1103 int res
= REAL(pthread_key_create
)(key
, dtor
);
1105 __msan_unpoison(key
, sizeof(*key
));
1109 #if SANITIZER_NETBSD
1110 INTERCEPTOR(int, __libc_thr_keycreate
, __sanitizer_pthread_key_t
*m
,
1111 void (*dtor
)(void *value
))
1112 ALIAS(WRAPPER_NAME(pthread_key_create
));
1115 INTERCEPTOR(int, pthread_join
, void *th
, void **retval
) {
1116 ENSURE_MSAN_INITED();
1117 int res
= REAL(pthread_join
)(th
, retval
);
1119 __msan_unpoison(retval
, sizeof(*retval
));
1123 DEFINE_REAL_PTHREAD_FUNCTIONS
1125 extern char *tzname
[2];
1127 INTERCEPTOR(void, tzset
, int fake
) {
1128 ENSURE_MSAN_INITED();
1129 InterceptorScope interceptor_scope
;
1132 __msan_unpoison(tzname
[0], internal_strlen(tzname
[0]) + 1);
1134 __msan_unpoison(tzname
[1], internal_strlen(tzname
[1]) + 1);
1138 struct MSanAtExitRecord
{
1139 void (*func
)(void *arg
);
1143 struct InterceptorContext
{
1145 Vector
<struct MSanAtExitRecord
*> AtExitStack
;
1147 InterceptorContext()
1152 static ALIGNED(64) char interceptor_placeholder
[sizeof(InterceptorContext
)];
1153 InterceptorContext
*interceptor_ctx() {
1154 return reinterpret_cast<InterceptorContext
*>(&interceptor_placeholder
[0]);
1157 void MSanAtExitWrapper() {
1158 MSanAtExitRecord
*r
;
1160 Lock
l(&interceptor_ctx()->atexit_mu
);
1162 uptr element
= interceptor_ctx()->AtExitStack
.Size() - 1;
1163 r
= interceptor_ctx()->AtExitStack
[element
];
1164 interceptor_ctx()->AtExitStack
.PopBack();
1168 ((void(*)())r
->func
)();
1172 void MSanCxaAtExitWrapper(void *arg
) {
1174 MSanAtExitRecord
*r
= (MSanAtExitRecord
*)arg
;
1175 // libc before 2.27 had race which caused occasional double handler execution
1176 // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1183 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
);
1185 // Unpoison argument shadow for C++ module destructors.
1186 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
1188 if (msan_init_is_running
) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
1189 return setup_at_exit_wrapper((void(*)())func
, arg
, dso_handle
);
1192 // Unpoison argument shadow for C++ module destructors.
1193 INTERCEPTOR(int, atexit
, void (*func
)()) {
1194 // Avoid calling real atexit as it is unreachable on at least on Linux.
1195 if (msan_init_is_running
)
1196 return REAL(__cxa_atexit
)((void (*)(void *a
))func
, 0, 0);
1197 return setup_at_exit_wrapper((void(*)())func
, 0, 0);
1200 static int setup_at_exit_wrapper(void(*f
)(), void *arg
, void *dso
) {
1201 ENSURE_MSAN_INITED();
1202 MSanAtExitRecord
*r
=
1203 (MSanAtExitRecord
*)InternalAlloc(sizeof(MSanAtExitRecord
));
1204 r
->func
= (void(*)(void *a
))f
;
1208 // NetBSD does not preserve the 2nd argument if dso is equal to 0
1209 // Store ctx in a local stack-like structure
1211 Lock
l(&interceptor_ctx()->atexit_mu
);
1213 res
= REAL(__cxa_atexit
)((void (*)(void *a
))MSanAtExitWrapper
, 0, 0);
1215 interceptor_ctx()->AtExitStack
.PushBack(r
);
1218 res
= REAL(__cxa_atexit
)(MSanCxaAtExitWrapper
, r
, dso
);
1223 static void BeforeFork() {
1224 StackDepotLockAll();
1225 ChainedOriginDepotLockAll();
1228 static void AfterFork() {
1229 ChainedOriginDepotUnlockAll();
1230 StackDepotUnlockAll();
1233 INTERCEPTOR(int, fork
, void) {
1234 ENSURE_MSAN_INITED();
1236 int pid
= REAL(fork
)();
1241 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1244 INTERCEPTOR(int, openpty
, int *aparent
, int *aworker
, char *name
,
1245 const void *termp
, const void *winp
) {
1246 ENSURE_MSAN_INITED();
1247 InterceptorScope interceptor_scope
;
1248 int res
= REAL(openpty
)(aparent
, aworker
, name
, termp
, winp
);
1250 __msan_unpoison(aparent
, sizeof(*aparent
));
1251 __msan_unpoison(aworker
, sizeof(*aworker
));
1255 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1257 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1260 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1263 INTERCEPTOR(int, forkpty
, int *aparent
, char *name
, const void *termp
,
1265 ENSURE_MSAN_INITED();
1266 InterceptorScope interceptor_scope
;
1267 int res
= REAL(forkpty
)(aparent
, name
, termp
, winp
);
1269 __msan_unpoison(aparent
, sizeof(*aparent
));
1272 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1274 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1277 struct MSanInterceptorContext
{
1278 bool in_interceptor_scope
;
1284 // FIXME: ask frontend whether we need to return failure.
1288 } // namespace __msan
1290 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1292 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1294 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1295 CHECK_UNPOISONED_0(x, n); \
1298 #define MSAN_INTERCEPT_FUNC(name) \
1300 if (!INTERCEPT_FUNCTION(name)) \
1301 VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1304 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1306 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
1307 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1310 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
1312 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
1313 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1314 #name, ver, #name); \
1317 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1318 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1319 MSAN_INTERCEPT_FUNC_VER(name, ver)
1320 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1321 MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1322 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1323 UnpoisonParam(count)
1324 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1325 __msan_unpoison(ptr, size)
1326 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1327 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1328 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1329 __msan_unpoison(ptr, size)
1330 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1331 if (msan_init_is_running) \
1332 return REAL(func)(__VA_ARGS__); \
1333 ENSURE_MSAN_INITED(); \
1334 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1335 ctx = (void *)&msan_ctx; \
1337 InterceptorScope interceptor_scope; \
1338 __msan_unpoison(__errno_location(), sizeof(int));
1339 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1342 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1345 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1348 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1351 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1353 } while (false) // FIXME
1354 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1356 } while (false) // FIXME
1357 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1358 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1359 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1361 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1362 if (filename && map) \
1363 ForEachMappedRegion(map, __msan_unpoison); \
1366 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1368 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1369 if (MsanThread *t = GetCurrentThread()) { \
1370 *begin = t->tls_begin(); \
1371 *end = t->tls_end(); \
1373 *begin = *end = 0; \
1376 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1379 return __msan_memset(block, c, size); \
1381 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1384 return __msan_memmove(to, from, size); \
1386 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1389 return __msan_memcpy(to, from, size); \
1392 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1394 GET_STORE_STACK_TRACE; \
1395 CopyShadowAndOrigin(to, from, size, &stack); \
1396 __msan_unpoison(to + size, 1); \
1399 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1402 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
1405 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1406 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1408 static uptr
signal_impl(int signo
, uptr cb
);
1409 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1410 __sanitizer_sigaction
*oldact
);
1412 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1413 { return sigaction_impl(signo, act, oldact); }
1415 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1417 handler = signal_impl(signo, handler); \
1418 InterceptorScope interceptor_scope; \
1419 return REAL(func)(signo, handler); \
1422 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1424 static int sigaction_impl(int signo
, const __sanitizer_sigaction
*act
,
1425 __sanitizer_sigaction
*oldact
) {
1426 ENSURE_MSAN_INITED();
1427 if (signo
<= 0 || signo
>= kMaxSignals
) {
1428 errno
= errno_EINVAL
;
1431 if (act
) read_sigaction(act
);
1433 if (flags()->wrap_signals
) {
1434 SpinMutexLock
lock(&sigactions_mu
);
1435 uptr old_cb
= atomic_load(&sigactions
[signo
], memory_order_relaxed
);
1436 __sanitizer_sigaction new_act
;
1437 __sanitizer_sigaction
*pnew_act
= act
? &new_act
: nullptr;
1439 REAL(memcpy
)(pnew_act
, act
, sizeof(__sanitizer_sigaction
));
1440 uptr cb
= (uptr
)pnew_act
->sigaction
;
1441 uptr new_cb
= (pnew_act
->sa_flags
& __sanitizer::sa_siginfo
)
1442 ? (uptr
)SignalAction
1443 : (uptr
)SignalHandler
;
1444 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1445 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1446 pnew_act
->sigaction
= (decltype(pnew_act
->sigaction
))new_cb
;
1449 res
= REAL(SIGACTION_SYMNAME
)(signo
, pnew_act
, oldact
);
1450 if (res
== 0 && oldact
) {
1451 uptr cb
= (uptr
)oldact
->sigaction
;
1452 if (cb
== (uptr
)SignalAction
|| cb
== (uptr
)SignalHandler
) {
1453 oldact
->sigaction
= (decltype(oldact
->sigaction
))old_cb
;
1457 res
= REAL(SIGACTION_SYMNAME
)(signo
, act
, oldact
);
1460 if (res
== 0 && oldact
) {
1461 __msan_unpoison(oldact
, sizeof(__sanitizer_sigaction
));
1466 static uptr
signal_impl(int signo
, uptr cb
) {
1467 ENSURE_MSAN_INITED();
1468 if (signo
<= 0 || signo
>= kMaxSignals
) {
1469 errno
= errno_EINVAL
;
1472 if (flags()->wrap_signals
) {
1473 SpinMutexLock
lock(&sigactions_mu
);
1474 if (cb
!= __sanitizer::sig_ign
&& cb
!= __sanitizer::sig_dfl
) {
1475 atomic_store(&sigactions
[signo
], cb
, memory_order_relaxed
);
1476 cb
= (uptr
)&SignalHandler
;
1482 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1483 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1486 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1489 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1490 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1491 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1493 INTERCEPTOR(const char *, strsignal
, int sig
) {
1495 COMMON_INTERCEPTOR_ENTER(ctx
, strsignal
, sig
);
1496 const char *res
= REAL(strsignal
)(sig
);
1498 __msan_unpoison(res
, internal_strlen(res
) + 1);
1509 INTERCEPTOR(int, dladdr
, void *addr
, dlinfo
*info
) {
1511 COMMON_INTERCEPTOR_ENTER(ctx
, dladdr
, addr
, info
);
1512 int res
= REAL(dladdr
)(addr
, info
);
1514 __msan_unpoison(info
, sizeof(*info
));
1515 if (info
->dli_fname
)
1516 __msan_unpoison(info
->dli_fname
, internal_strlen(info
->dli_fname
) + 1);
1517 if (info
->dli_sname
)
1518 __msan_unpoison(info
->dli_sname
, internal_strlen(info
->dli_sname
) + 1);
1523 INTERCEPTOR(char *, dlerror
, int fake
) {
1525 COMMON_INTERCEPTOR_ENTER(ctx
, dlerror
, fake
);
1526 char *res
= REAL(dlerror
)(fake
);
1528 __msan_unpoison(res
, internal_strlen(res
) + 1);
1532 typedef int (*dl_iterate_phdr_cb
)(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1534 struct dl_iterate_phdr_data
{
1535 dl_iterate_phdr_cb callback
;
1539 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info
*info
, SIZE_T size
,
1542 __msan_unpoison(info
, size
);
1543 if (info
->dlpi_phdr
&& info
->dlpi_phnum
)
1544 __msan_unpoison(info
->dlpi_phdr
, struct_ElfW_Phdr_sz
* info
->dlpi_phnum
);
1545 if (info
->dlpi_name
)
1546 __msan_unpoison(info
->dlpi_name
, internal_strlen(info
->dlpi_name
) + 1);
1548 dl_iterate_phdr_data
*cbdata
= (dl_iterate_phdr_data
*)data
;
1550 return cbdata
->callback(info
, size
, cbdata
->data
);
1553 INTERCEPTOR(void *, shmat
, int shmid
, const void *shmaddr
, int shmflg
) {
1554 ENSURE_MSAN_INITED();
1555 void *p
= REAL(shmat
)(shmid
, shmaddr
, shmflg
);
1556 if (p
!= (void *)-1) {
1557 __sanitizer_shmid_ds ds
;
1558 int res
= REAL(shmctl
)(shmid
, shmctl_ipc_stat
, &ds
);
1560 __msan_unpoison(p
, ds
.shm_segsz
);
1566 INTERCEPTOR(int, dl_iterate_phdr
, dl_iterate_phdr_cb callback
, void *data
) {
1568 COMMON_INTERCEPTOR_ENTER(ctx
, dl_iterate_phdr
, callback
, data
);
1569 dl_iterate_phdr_data cbdata
;
1570 cbdata
.callback
= callback
;
1572 int res
= REAL(dl_iterate_phdr
)(msan_dl_iterate_phdr_cb
, (void *)&cbdata
);
1576 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
1577 INTERCEPTOR(wchar_t *, wcschr
, void *s
, wchar_t wc
, void *ps
) {
1578 ENSURE_MSAN_INITED();
1579 wchar_t *res
= REAL(wcschr
)(s
, wc
, ps
);
1583 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
1584 INTERCEPTOR(wchar_t *, wcscpy
, wchar_t *dest
, const wchar_t *src
) {
1585 ENSURE_MSAN_INITED();
1586 GET_STORE_STACK_TRACE
;
1587 wchar_t *res
= REAL(wcscpy
)(dest
, src
);
1588 CopyShadowAndOrigin(dest
, src
, sizeof(wchar_t) * (internal_wcslen(src
) + 1),
1593 INTERCEPTOR(wchar_t *, wcsncpy
, wchar_t *dest
, const wchar_t *src
, SIZE_T n
) {
1594 ENSURE_MSAN_INITED();
1595 GET_STORE_STACK_TRACE
;
1596 SIZE_T copy_size
= internal_wcsnlen(src
, n
);
1597 if (copy_size
< n
) copy_size
++; // trailing \0
1598 wchar_t *res
= REAL(wcsncpy
)(dest
, src
, n
);
1599 CopyShadowAndOrigin(dest
, src
, copy_size
* sizeof(wchar_t), &stack
);
1600 __msan_unpoison(dest
+ copy_size
, (n
- copy_size
) * sizeof(wchar_t));
1604 // These interface functions reside here so that they can use
1605 // REAL(memset), etc.
1606 void __msan_unpoison(const void *a
, uptr size
) {
1607 if (!MEM_IS_APP(a
)) return;
1608 SetShadow(a
, size
, 0);
1611 void __msan_poison(const void *a
, uptr size
) {
1612 if (!MEM_IS_APP(a
)) return;
1613 SetShadow(a
, size
, __msan::flags()->poison_heap_with_zeroes
? 0 : -1);
1616 void __msan_poison_stack(void *a
, uptr size
) {
1617 if (!MEM_IS_APP(a
)) return;
1618 SetShadow(a
, size
, __msan::flags()->poison_stack_with_zeroes
? 0 : -1);
1621 void __msan_unpoison_param(uptr n
) { UnpoisonParam(n
); }
1623 void __msan_clear_and_unpoison(void *a
, uptr size
) {
1624 REAL(memset
)(a
, 0, size
);
1625 SetShadow(a
, size
, 0);
1628 void *__msan_memcpy(void *dest
, const void *src
, SIZE_T n
) {
1629 if (!msan_inited
) return internal_memcpy(dest
, src
, n
);
1630 if (msan_init_is_running
|| __msan::IsInSymbolizerOrUnwider())
1631 return REAL(memcpy
)(dest
, src
, n
);
1632 ENSURE_MSAN_INITED();
1633 GET_STORE_STACK_TRACE
;
1634 void *res
= REAL(memcpy
)(dest
, src
, n
);
1635 CopyShadowAndOrigin(dest
, src
, n
, &stack
);
1639 void *__msan_memset(void *s
, int c
, SIZE_T n
) {
1640 if (!msan_inited
) return internal_memset(s
, c
, n
);
1641 if (msan_init_is_running
) return REAL(memset
)(s
, c
, n
);
1642 ENSURE_MSAN_INITED();
1643 void *res
= REAL(memset
)(s
, c
, n
);
1644 __msan_unpoison(s
, n
);
1648 void *__msan_memmove(void *dest
, const void *src
, SIZE_T n
) {
1649 if (!msan_inited
) return internal_memmove(dest
, src
, n
);
1650 if (msan_init_is_running
) return REAL(memmove
)(dest
, src
, n
);
1651 ENSURE_MSAN_INITED();
1652 GET_STORE_STACK_TRACE
;
1653 void *res
= REAL(memmove
)(dest
, src
, n
);
1654 MoveShadowAndOrigin(dest
, src
, n
, &stack
);
1658 void __msan_unpoison_string(const char* s
) {
1659 if (!MEM_IS_APP(s
)) return;
1660 __msan_unpoison(s
, internal_strlen(s
) + 1);
1665 void InitializeInterceptors() {
1666 static int inited
= 0;
1667 CHECK_EQ(inited
, 0);
1669 new(interceptor_ctx()) InterceptorContext();
1671 InitializeCommonInterceptors();
1672 InitializeSignalInterceptors();
1674 INTERCEPT_FUNCTION(posix_memalign
);
1675 MSAN_MAYBE_INTERCEPT_MEMALIGN
;
1676 MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
;
1677 INTERCEPT_FUNCTION(valloc
);
1678 MSAN_MAYBE_INTERCEPT_PVALLOC
;
1679 INTERCEPT_FUNCTION(malloc
);
1680 INTERCEPT_FUNCTION(calloc
);
1681 INTERCEPT_FUNCTION(realloc
);
1682 INTERCEPT_FUNCTION(reallocarray
);
1683 INTERCEPT_FUNCTION(free
);
1684 MSAN_MAYBE_INTERCEPT_CFREE
;
1685 MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
;
1686 MSAN_MAYBE_INTERCEPT_MALLINFO
;
1687 MSAN_MAYBE_INTERCEPT_MALLOPT
;
1688 MSAN_MAYBE_INTERCEPT_MALLOC_STATS
;
1689 INTERCEPT_FUNCTION(fread
);
1690 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
;
1691 INTERCEPT_FUNCTION(memccpy
);
1692 MSAN_MAYBE_INTERCEPT_MEMPCPY
;
1693 INTERCEPT_FUNCTION(bcopy
);
1694 INTERCEPT_FUNCTION(wmemset
);
1695 INTERCEPT_FUNCTION(wmemcpy
);
1696 MSAN_MAYBE_INTERCEPT_WMEMPCPY
;
1697 INTERCEPT_FUNCTION(wmemmove
);
1698 INTERCEPT_FUNCTION(strcpy
);
1699 MSAN_MAYBE_INTERCEPT_STPCPY
;
1700 MSAN_MAYBE_INTERCEPT_STPNCPY
;
1701 INTERCEPT_FUNCTION(strdup
);
1702 MSAN_MAYBE_INTERCEPT___STRDUP
;
1703 INTERCEPT_FUNCTION(strncpy
);
1704 MSAN_MAYBE_INTERCEPT_GCVT
;
1705 INTERCEPT_FUNCTION(strcat
);
1706 INTERCEPT_FUNCTION(strncat
);
1707 INTERCEPT_STRTO(strtod
);
1708 INTERCEPT_STRTO(strtof
);
1709 INTERCEPT_STRTO(strtold
);
1710 INTERCEPT_STRTO(strtol
);
1711 INTERCEPT_STRTO(strtoul
);
1712 INTERCEPT_STRTO(strtoll
);
1713 INTERCEPT_STRTO(strtoull
);
1714 INTERCEPT_STRTO(strtouq
);
1715 INTERCEPT_STRTO(wcstod
);
1716 INTERCEPT_STRTO(wcstof
);
1717 INTERCEPT_STRTO(wcstold
);
1718 INTERCEPT_STRTO(wcstol
);
1719 INTERCEPT_STRTO(wcstoul
);
1720 INTERCEPT_STRTO(wcstoll
);
1721 INTERCEPT_STRTO(wcstoull
);
1722 #ifdef SANITIZER_NLDBL_VERSION
1723 INTERCEPT_FUNCTION_VER(vswprintf
, SANITIZER_NLDBL_VERSION
);
1724 INTERCEPT_FUNCTION_VER(swprintf
, SANITIZER_NLDBL_VERSION
);
1726 INTERCEPT_FUNCTION(vswprintf
);
1727 INTERCEPT_FUNCTION(swprintf
);
1729 INTERCEPT_FUNCTION(strftime
);
1730 INTERCEPT_FUNCTION(strftime_l
);
1731 MSAN_MAYBE_INTERCEPT___STRFTIME_L
;
1732 INTERCEPT_FUNCTION(wcsftime
);
1733 INTERCEPT_FUNCTION(wcsftime_l
);
1734 MSAN_MAYBE_INTERCEPT___WCSFTIME_L
;
1735 INTERCEPT_FUNCTION(mbtowc
);
1736 INTERCEPT_FUNCTION(mbrtowc
);
1737 INTERCEPT_FUNCTION(wcslen
);
1738 INTERCEPT_FUNCTION(wcsnlen
);
1739 INTERCEPT_FUNCTION(wcschr
);
1740 INTERCEPT_FUNCTION(wcscpy
);
1741 INTERCEPT_FUNCTION(wcsncpy
);
1742 INTERCEPT_FUNCTION(wcscmp
);
1743 INTERCEPT_FUNCTION(getenv
);
1744 INTERCEPT_FUNCTION(setenv
);
1745 INTERCEPT_FUNCTION(putenv
);
1746 INTERCEPT_FUNCTION(gettimeofday
);
1747 MSAN_MAYBE_INTERCEPT_FCVT
;
1748 MSAN_MAYBE_INTERCEPT_FSTAT
;
1749 MSAN_MAYBE_INTERCEPT_FSTAT64
;
1750 MSAN_MAYBE_INTERCEPT___FXSTAT
;
1751 MSAN_MAYBE_INTERCEPT_FSTATAT
;
1752 MSAN_MAYBE_INTERCEPT_FSTATAT64
;
1753 MSAN_MAYBE_INTERCEPT___FXSTATAT
;
1754 MSAN_MAYBE_INTERCEPT___FXSTAT64
;
1755 MSAN_MAYBE_INTERCEPT___FXSTATAT64
;
1756 INTERCEPT_FUNCTION(pipe
);
1757 INTERCEPT_FUNCTION(pipe2
);
1758 INTERCEPT_FUNCTION(socketpair
);
1759 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
;
1760 INTERCEPT_FUNCTION(getrlimit
);
1761 MSAN_MAYBE_INTERCEPT___GETRLIMIT
;
1762 MSAN_MAYBE_INTERCEPT_GETRLIMIT64
;
1763 MSAN_MAYBE_INTERCEPT_PRLIMIT
;
1764 MSAN_MAYBE_INTERCEPT_PRLIMIT64
;
1765 INTERCEPT_FUNCTION(gethostname
);
1766 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
;
1767 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
;
1768 INTERCEPT_FUNCTION(strsignal
);
1769 INTERCEPT_FUNCTION(dladdr
);
1770 INTERCEPT_FUNCTION(dlerror
);
1771 INTERCEPT_FUNCTION(dl_iterate_phdr
);
1772 INTERCEPT_FUNCTION(getrusage
);
1773 #if defined(__mips__)
1774 INTERCEPT_FUNCTION_VER(pthread_create
, "GLIBC_2.2");
1776 INTERCEPT_FUNCTION(pthread_create
);
1778 INTERCEPT_FUNCTION(pthread_join
);
1779 INTERCEPT_FUNCTION(pthread_key_create
);
1781 #if SANITIZER_NETBSD
1782 INTERCEPT_FUNCTION(__libc_thr_keycreate
);
1785 INTERCEPT_FUNCTION(pthread_join
);
1786 INTERCEPT_FUNCTION(tzset
);
1787 INTERCEPT_FUNCTION(atexit
);
1788 INTERCEPT_FUNCTION(__cxa_atexit
);
1789 INTERCEPT_FUNCTION(shmat
);
1790 INTERCEPT_FUNCTION(fork
);
1791 MSAN_MAYBE_INTERCEPT_OPENPTY
;
1792 MSAN_MAYBE_INTERCEPT_FORKPTY
;
1796 } // namespace __msan