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