1//===-- asan_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 AddressSanitizer, an address sanity checker.
10//
11// Intercept various libc functions.
12//===----------------------------------------------------------------------===//
13
14#include "asan_interceptors.h"
15
16#include "asan_allocator.h"
17#include "asan_internal.h"
18#include "asan_mapping.h"
19#include "asan_poisoning.h"
20#include "asan_report.h"
21#include "asan_stack.h"
22#include "asan_stats.h"
23#include "asan_suppressions.h"
24#include "asan_thread.h"
25#include "lsan/lsan_common.h"
26#include "sanitizer_common/sanitizer_errno.h"
27#include "sanitizer_common/sanitizer_internal_defs.h"
28#include "sanitizer_common/sanitizer_libc.h"
29
30// There is no general interception at all on Fuchsia.
31// Only the functions in asan_interceptors_memintrinsics.cpp are
32// really defined to replace libc functions.
33#if !SANITIZER_FUCHSIA
34
35# if SANITIZER_POSIX
36# include "sanitizer_common/sanitizer_posix.h"
37# endif
38
39# if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
40 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
41# include <unwind.h>
42# endif
43
44# if defined(__i386) && SANITIZER_LINUX
45# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
46# elif defined(__mips__) && SANITIZER_LINUX
47# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
48# endif
49
50namespace __asan {
51
52# define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
53 ASAN_READ_RANGE((ctx), (s), \
54 common_flags()->strict_string_checks ? (len) + 1 : (n))
55
56# define ASAN_READ_STRING(ctx, s, n) \
57 ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
58
59static inline uptr MaybeRealStrnlen(const char* s, uptr maxlen) {
60# if SANITIZER_INTERCEPT_STRNLEN
61 if (static_cast<bool>(REAL(strnlen)))
62 return REAL(strnlen)(s, maxlen);
63# endif
64 return internal_strnlen(s, maxlen);
65}
66
67static inline uptr MaybeRealWcsnlen(const wchar_t* s, uptr maxlen) {
68# if SANITIZER_INTERCEPT_WCSNLEN
69 if (static_cast<bool>(REAL(wcsnlen)))
70 return REAL(wcsnlen)(s, maxlen);
71# endif
72 return internal_wcsnlen(s, maxlen);
73}
74
75void SetThreadName(const char* name) {
76 AsanThread* t = GetCurrentThread();
77 if (t)
78 asanThreadRegistry().SetThreadName(tid: t->tid(), name);
79}
80
81int OnExit() {
82 if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
83 __lsan::HasReportedLeaks()) {
84 return common_flags()->exitcode;
85 }
86 // FIXME: ask frontend whether we need to return failure.
87 return 0;
88}
89
90} // namespace __asan
91
92// ---------------------- Wrappers ---------------- {{{1
93using namespace __asan;
94
95DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, usize)
96DECLARE_REAL_AND_INTERCEPTOR(void, free, void*)
97
98# define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
99 ASAN_INTERCEPT_FUNC_VER(name, ver)
100# define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
101 ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
102# define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
103 ASAN_WRITE_RANGE(ctx, ptr, size)
104# define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
105 ASAN_READ_RANGE(ctx, ptr, size)
106# define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
107 ASAN_INTERCEPTOR_ENTER(ctx, func); \
108 do { \
109 if constexpr (SANITIZER_APPLE) { \
110 if (UNLIKELY(!AsanInited())) \
111 return REAL(func)(__VA_ARGS__); \
112 } else { \
113 if (!TryAsanInitFromRtl()) \
114 return REAL(func)(__VA_ARGS__); \
115 } \
116 } while (false)
117# define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
118 do { \
119 } while (false)
120# define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
121 do { \
122 } while (false)
123# define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
124 do { \
125 } while (false)
126# define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
127 do { \
128 } while (false)
129# define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
130// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
131// But asan does not remember UserId's for threads (pthread_t);
132// and remembers all ever existed threads, so the linear search by UserId
133// can be slow.
134# define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
135 do { \
136 } while (false)
137# define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
138// Strict init-order checking is dlopen-hostile:
139// https://github.com/google/sanitizers/issues/178
140# define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
141 ({ \
142 if (flags()->strict_init_order) \
143 StopInitOrderChecking(); \
144 CheckNoDeepBind(filename, flag); \
145 REAL(dlopen)(filename, flag); \
146 })
147# define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
148# define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
149# define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
150# define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!AsanInited())
151# define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
152 if (AsanThread* t = GetCurrentThread()) { \
153 *begin = t->tls_begin(); \
154 *end = t->tls_end(); \
155 } else { \
156 *begin = *end = 0; \
157 }
158
159template <class Mmap>
160static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
161 int prot, int flags, int fd, OFF64_T offset) {
162 void* res = real_mmap(addr, length, prot, flags, fd, offset);
163 if (length && res != (void*)-1) {
164 const uptr beg = reinterpret_cast<uptr>(res);
165 DCHECK(IsAligned(beg, GetPageSize()));
166 SIZE_T rounded_length = RoundUpTo(size: length, boundary: GetPageSize());
167 // Only unpoison shadow if it's an ASAN managed address.
168 if (AddrIsInMem(a: beg) && AddrIsInMem(a: beg + rounded_length - 1))
169 PoisonShadow(addr: beg, size: RoundUpTo(size: length, boundary: GetPageSize()), value: 0);
170 }
171 return res;
172}
173
174template <class Munmap>
175static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
176 // We should not tag if munmap fail, but it's to late to tag after
177 // real_munmap, as the pages could be mmaped by another thread.
178 const uptr beg = reinterpret_cast<uptr>(addr);
179 if (length && IsAligned(a: beg, alignment: GetPageSize())) {
180 SIZE_T rounded_length = RoundUpTo(size: length, boundary: GetPageSize());
181 // Protect from unmapping the shadow.
182 if (AddrIsInMem(a: beg) && AddrIsInMem(a: beg + rounded_length - 1))
183 PoisonShadow(addr: beg, size: rounded_length, value: 0);
184 }
185 return real_munmap(addr, length);
186}
187
188# define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
189 fd, offset) \
190 do { \
191 (void)(ctx); \
192 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
193 } while (false)
194
195# define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
196 do { \
197 (void)(ctx); \
198 return munmap_interceptor(REAL(munmap), addr, sz); \
199 } while (false)
200
201# if CAN_SANITIZE_LEAKS
202# define COMMON_INTERCEPTOR_STRERROR() \
203 __lsan::ScopedInterceptorDisabler disabler
204# endif
205
206# define SIGNAL_INTERCEPTOR_ENTER() \
207 do { \
208 AsanInitFromRtl(); \
209 } while (false)
210
211# include "sanitizer_common/sanitizer_common_interceptors.inc"
212# include "sanitizer_common/sanitizer_signal_interceptors.inc"
213
214// Syscall interceptors don't have contexts, we don't support suppressions
215// for them.
216# define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
217# define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
218# define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
219 do { \
220 (void)(p); \
221 (void)(s); \
222 } while (false)
223# define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
224 do { \
225 (void)(p); \
226 (void)(s); \
227 } while (false)
228# include "sanitizer_common/sanitizer_common_syscalls.inc"
229# include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
230
231# if ASAN_INTERCEPT_PTHREAD_CREATE
232static thread_return_t THREAD_CALLING_CONV asan_thread_start(void* arg) {
233 AsanThread* t = (AsanThread*)arg;
234 SetCurrentThread(t);
235 auto self = GetThreadSelf();
236 auto args = asanThreadArgRetval().GetArgs(thread: self);
237 t->ThreadStart(os_id: GetTid());
238
239# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
240 SANITIZER_SOLARIS
241 __sanitizer_sigset_t sigset;
242 t->GetStartData(data&: sigset);
243 SetSigProcMask(set: &sigset, oldset: nullptr);
244# endif
245
246 thread_return_t retval = (*args.routine)(args.arg_retval);
247 asanThreadArgRetval().Finish(thread: self, retval);
248 return retval;
249}
250
251INTERCEPTOR(int, pthread_create, void* thread, void* attr,
252 void* (*start_routine)(void*), void* arg) {
253 EnsureMainThreadIDIsCorrect();
254 // Strict init-order checking is thread-hostile.
255 if (flags()->strict_init_order)
256 StopInitOrderChecking();
257 GET_STACK_TRACE_THREAD;
258 bool detached = [attr]() {
259 int d = 0;
260 return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) &&
261 IsStateDetached(state: d);
262 }();
263
264 u32 current_tid = GetCurrentTidOrInvalid();
265
266 __sanitizer_sigset_t sigset = {};
267# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
268 SANITIZER_SOLARIS
269 ScopedBlockSignals block(&sigset);
270# endif
271
272 AsanThread* t = AsanThread::Create(data: sigset, parent_tid: current_tid, stack: &stack, detached);
273
274 int result;
275 {
276 // Ignore all allocations made by pthread_create: thread stack/TLS may be
277 // stored by pthread for future reuse even after thread destruction, and
278 // the linked list it's stored in doesn't even hold valid pointers to the
279 // objects, the latter are calculated by obscure pointer arithmetic.
280# if CAN_SANITIZE_LEAKS
281 __lsan::ScopedInterceptorDisabler disabler;
282# endif
283 asanThreadArgRetval().Create(detached, args: {.routine: start_routine, .arg_retval: arg}, fn: [&]() -> uptr {
284 result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
285// AIX pthread_t is unsigned int.
286# if SANITIZER_AIX
287 return result ? 0 : *(unsigned*)(thread);
288# else
289 return result ? 0 : *(uptr*)(thread);
290# endif
291 });
292 }
293 if (result != 0) {
294 // If the thread didn't start delete the AsanThread to avoid leaking it.
295 // Note AsanThreadContexts never get destroyed so the AsanThreadContext
296 // that was just created for the AsanThread is wasted.
297 t->Destroy();
298 }
299 return result;
300}
301
302INTERCEPTOR(int, pthread_join, void* thread, void** retval) {
303 int result;
304 asanThreadArgRetval().Join(thread: (uptr)thread, fn: [&]() {
305 result = REAL(pthread_join)(thread, retval);
306 return !result;
307 });
308 return result;
309}
310
311INTERCEPTOR(int, pthread_detach, void* thread) {
312 int result;
313 asanThreadArgRetval().Detach(thread: (uptr)thread, fn: [&]() {
314 result = REAL(pthread_detach)(thread);
315 return !result;
316 });
317 return result;
318}
319
320INTERCEPTOR(void, pthread_exit, void* retval) {
321 asanThreadArgRetval().Finish(thread: GetThreadSelf(), retval);
322 REAL(pthread_exit)(retval);
323}
324
325# if ASAN_INTERCEPT_TRYJOIN
326INTERCEPTOR(int, pthread_tryjoin_np, void* thread, void** ret) {
327 int result;
328 asanThreadArgRetval().Join(thread: (uptr)thread, fn: [&]() {
329 result = REAL(pthread_tryjoin_np)(thread, ret);
330 return !result;
331 });
332 return result;
333}
334# endif
335
336# if ASAN_INTERCEPT_TIMEDJOIN
337INTERCEPTOR(int, pthread_timedjoin_np, void* thread, void** ret,
338 const struct timespec* abstime) {
339 int result;
340 asanThreadArgRetval().Join(thread: (uptr)thread, fn: [&]() {
341 result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
342 return !result;
343 });
344 return result;
345}
346# endif
347
348DEFINE_INTERNAL_PTHREAD_FUNCTIONS
349# endif // ASAN_INTERCEPT_PTHREAD_CREATE
350
351# if ASAN_INTERCEPT_SWAPCONTEXT
352static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
353 // Only clear if we know the stack. This should be true only for contexts
354 // created with makecontext().
355 if (!ssize)
356 return;
357 // Align to page size.
358 uptr PageSize = GetPageSizeCached();
359 uptr bottom = RoundDownTo(x: stack, boundary: PageSize);
360 if (!AddrIsInMem(a: bottom))
361 return;
362 ssize += stack - bottom;
363 ssize = RoundUpTo(size: ssize, boundary: PageSize);
364 PoisonShadow(addr: bottom, size: ssize, value: 0);
365}
366
367// Since Solaris 10/SPARC, ucp->uc_stack.ss_sp refers to the stack base address
368// as on other targets. For binary compatibility, the new version uses a
369// different external name, so we intercept that.
370# if SANITIZER_SOLARIS && defined(__sparc__)
371INTERCEPTOR(void, __makecontext_v2, struct ucontext_t* ucp, void (*func)(),
372 int argc, ...) {
373# else
374INTERCEPTOR(void, makecontext, struct ucontext_t* ucp, void (*func)(), int argc,
375 ...) {
376# endif
377 va_list ap;
378 uptr args[64];
379 // We don't know a better way to forward ... into REAL function. We can
380 // increase args size if necessary.
381 CHECK_LE(argc, ARRAY_SIZE(args));
382 internal_memset(s: args, c: 0, n: sizeof(args));
383 va_start(ap, argc);
384 for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
385 va_end(ap);
386
387# define ENUMERATE_ARRAY_4(start) \
388 args[start], args[start + 1], args[start + 2], args[start + 3]
389# define ENUMERATE_ARRAY_16(start) \
390 ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
391 ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
392# define ENUMERATE_ARRAY_64() \
393 ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
394 ENUMERATE_ARRAY_16(48)
395
396# if SANITIZER_SOLARIS && defined(__sparc__)
397 REAL(__makecontext_v2)
398# else
399 REAL(makecontext)
400# endif
401 ((struct ucontext_t*)ucp, func, argc, ENUMERATE_ARRAY_64());
402
403# undef ENUMERATE_ARRAY_4
404# undef ENUMERATE_ARRAY_16
405# undef ENUMERATE_ARRAY_64
406
407 // Sign the stack so we can identify it for unpoisoning.
408 SignContextStack(context: ucp);
409}
410
411INTERCEPTOR(int, swapcontext, struct ucontext_t* oucp, struct ucontext_t* ucp) {
412 static bool reported_warning = false;
413 if (!reported_warning) {
414 Report(
415 format: "WARNING: ASan doesn't fully support makecontext/swapcontext "
416 "functions and may produce false positives in some cases!\n");
417 reported_warning = true;
418 }
419 // Clear shadow memory for new context (it may share stack
420 // with current context).
421 uptr stack, ssize;
422 ReadContextStack(context: ucp, stack: &stack, ssize: &ssize);
423 ClearShadowMemoryForContextStack(stack, ssize);
424
425# if __has_attribute(__indirect_return__) && \
426 (defined(__x86_64__) || defined(__i386__))
427 int (*real_swapcontext)(struct ucontext_t*, struct ucontext_t*)
428 __attribute__((__indirect_return__)) = REAL(swapcontext);
429 int res = real_swapcontext(oucp, ucp);
430# else
431 int res = REAL(swapcontext)(oucp, ucp);
432# endif
433 // swapcontext technically does not return, but program may swap context to
434 // "oucp" later, that would look as if swapcontext() returned 0.
435 // We need to clear shadow for ucp once again, as it may be in arbitrary
436 // state.
437 ClearShadowMemoryForContextStack(stack, ssize);
438 return res;
439}
440# endif // ASAN_INTERCEPT_SWAPCONTEXT
441
442# if SANITIZER_NETBSD
443# define longjmp __longjmp14
444# define siglongjmp __siglongjmp14
445# endif
446
447# if ASAN_INTERCEPT_LONGJMP
448INTERCEPTOR(void, longjmp, void* env, int val) {
449 __asan_handle_no_return();
450 REAL(longjmp)(env, val);
451}
452# endif
453
454# if ASAN_INTERCEPT__LONGJMP
455INTERCEPTOR(void, _longjmp, void* env, int val) {
456 __asan_handle_no_return();
457 REAL(_longjmp)(env, val);
458}
459# endif
460
461# if ASAN_INTERCEPT___LONGJMP_CHK
462INTERCEPTOR(void, __longjmp_chk, void* env, int val) {
463 __asan_handle_no_return();
464 REAL(__longjmp_chk)(env, val);
465}
466# endif
467
468# if ASAN_INTERCEPT_SIGLONGJMP
469INTERCEPTOR(void, siglongjmp, void* env, int val) {
470 __asan_handle_no_return();
471 REAL(siglongjmp)(env, val);
472}
473# endif
474
475# if ASAN_INTERCEPT___CXA_THROW
476INTERCEPTOR(void, __cxa_throw, void* a, void* b, void* c) {
477 CHECK(REAL(__cxa_throw));
478 __asan_handle_no_return();
479 REAL(__cxa_throw)(a, b, c);
480}
481# endif
482
483# if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
484INTERCEPTOR(void, __cxa_rethrow_primary_exception, void* a) {
485 CHECK(REAL(__cxa_rethrow_primary_exception));
486 __asan_handle_no_return();
487 REAL(__cxa_rethrow_primary_exception)(a);
488}
489# endif
490
491# if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
492INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
493 _Unwind_Exception* object) {
494 CHECK(REAL(_Unwind_RaiseException));
495 __asan_handle_no_return();
496 return REAL(_Unwind_RaiseException)(object);
497}
498# endif
499
500# if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
501INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
502 _Unwind_Exception* object) {
503 CHECK(REAL(_Unwind_SjLj_RaiseException));
504 __asan_handle_no_return();
505 return REAL(_Unwind_SjLj_RaiseException)(object);
506}
507# endif
508
509# if ASAN_INTERCEPT_INDEX
510# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
511INTERCEPTOR(char*, index, const char* string, int c)
512ALIAS(WRAP(strchr));
513# else
514# if SANITIZER_APPLE
515DECLARE_REAL(char*, index, const char* string, int c)
516OVERRIDE_FUNCTION(index, strchr);
517# else
518DEFINE_REAL(char*, index, const char* string, int c)
519# endif
520# endif
521# endif // ASAN_INTERCEPT_INDEX
522
523// For both strcat() and strncat() we need to check the validity of |to|
524// argument irrespective of the |from| length.
525INTERCEPTOR(char*, strcat, char* to, const char* from) {
526 void* ctx;
527 ASAN_INTERCEPTOR_ENTER(ctx, strcat);
528 AsanInitFromRtl();
529 if (flags()->replace_str) {
530 uptr from_length = internal_strlen(s: from);
531 ASAN_READ_RANGE(ctx, from, from_length + 1);
532 uptr to_length = internal_strlen(s: to);
533 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
534 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
535 // If the copying actually happens, the |from| string should not overlap
536 // with the resulting string starting at |to|, which has a length of
537 // to_length + from_length + 1.
538 if (from_length > 0) {
539 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
540 from_length + 1);
541 }
542 }
543 return REAL(strcat)(to, from);
544}
545
546INTERCEPTOR(char*, strncat, char* to, const char* from, usize size) {
547 void* ctx;
548 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
549 AsanInitFromRtl();
550 if (flags()->replace_str) {
551 uptr from_length = MaybeRealStrnlen(s: from, maxlen: size);
552 uptr copy_length = Min<uptr>(a: size, b: from_length + 1);
553 ASAN_READ_RANGE(ctx, from, copy_length);
554 uptr to_length = internal_strlen(s: to);
555 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
556 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
557 if (from_length > 0) {
558 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, from,
559 copy_length);
560 }
561 }
562 return REAL(strncat)(to, from, size);
563}
564
565INTERCEPTOR(char*, strcpy, char* to, const char* from) {
566 void* ctx;
567 ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
568 if constexpr (SANITIZER_APPLE) {
569 // strcpy is called from malloc_default_purgeable_zone()
570 // in __asan::ReplaceSystemAlloc() on Mac.
571 if (UNLIKELY(!AsanInited()))
572 return REAL(strcpy)(to, from);
573 } else {
574 if (!TryAsanInitFromRtl())
575 return REAL(strcpy)(to, from);
576 }
577
578 if (flags()->replace_str) {
579 uptr from_size = internal_strlen(s: from) + 1;
580 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
581 ASAN_READ_RANGE(ctx, from, from_size);
582 ASAN_WRITE_RANGE(ctx, to, from_size);
583 }
584 return REAL(strcpy)(to, from);
585}
586
587INTERCEPTOR(wchar_t*, wcscpy, wchar_t* to, const wchar_t* from) {
588 void* ctx;
589 ASAN_INTERCEPTOR_ENTER(ctx, wcscpy);
590 if (!TryAsanInitFromRtl())
591 return REAL(wcscpy)(to, from);
592 if (flags()->replace_str) {
593 uptr size = (internal_wcslen(s: from) + 1) * sizeof(wchar_t);
594 CHECK_RANGES_OVERLAP("wcscpy", to, size, from, size);
595 ASAN_READ_RANGE(ctx, from, size);
596 ASAN_WRITE_RANGE(ctx, to, size);
597 }
598 return REAL(wcscpy)(to, from);
599}
600
601// Windows doesn't always define the strdup identifier,
602// and when it does it's a macro defined to either _strdup
603// or _strdup_dbg, _strdup_dbg ends up calling _strdup, so
604// we want to intercept that. push/pop_macro are used to avoid problems
605// if this file ends up including <string.h> in the future.
606# if SANITIZER_WINDOWS
607# pragma push_macro("strdup")
608# undef strdup
609# define strdup _strdup
610# endif
611
612INTERCEPTOR(char*, strdup, const char* s) {
613 void* ctx;
614 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
615 // Allowing null input is Windows-specific
616 if (SANITIZER_WINDOWS && UNLIKELY(!s))
617 return nullptr;
618 if (UNLIKELY(!TryAsanInitFromRtl()))
619 return internal_strdup(s);
620 uptr length = internal_strlen(s);
621 if (flags()->replace_str) {
622 ASAN_READ_RANGE(ctx, s, length + 1);
623 }
624 GET_STACK_TRACE_MALLOC;
625 void* new_mem = asan_malloc(size: length + 1, stack: &stack);
626 if (new_mem) {
627 REAL(memcpy)(new_mem, s, length + 1);
628 }
629 return reinterpret_cast<char*>(new_mem);
630}
631
632# if ASAN_INTERCEPT___STRDUP
633INTERCEPTOR(char*, __strdup, const char* s) {
634 void* ctx;
635 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
636 if (UNLIKELY(!TryAsanInitFromRtl()))
637 return internal_strdup(s);
638 uptr length = internal_strlen(s);
639 if (flags()->replace_str) {
640 ASAN_READ_RANGE(ctx, s, length + 1);
641 }
642 GET_STACK_TRACE_MALLOC;
643 void* new_mem = asan_malloc(size: length + 1, stack: &stack);
644 if (new_mem) {
645 REAL(memcpy)(new_mem, s, length + 1);
646 }
647 return reinterpret_cast<char*>(new_mem);
648}
649# endif // ASAN_INTERCEPT___STRDUP
650
651INTERCEPTOR(char*, strncpy, char* to, const char* from, usize size) {
652 void* ctx;
653 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
654 AsanInitFromRtl();
655 if (flags()->replace_str) {
656 uptr from_size = Min<uptr>(a: size, b: MaybeRealStrnlen(s: from, maxlen: size) + 1);
657 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
658 ASAN_READ_RANGE(ctx, from, from_size);
659 ASAN_WRITE_RANGE(ctx, to, size);
660 }
661 return REAL(strncpy)(to, from, size);
662}
663
664INTERCEPTOR(wchar_t*, wcsncpy, wchar_t* to, const wchar_t* from, uptr size) {
665 void* ctx;
666 ASAN_INTERCEPTOR_ENTER(ctx, wcsncpy);
667 AsanInitFromRtl();
668 if (flags()->replace_str) {
669 uptr from_size =
670 Min(a: size, b: MaybeRealWcsnlen(s: from, maxlen: size) + 1) * sizeof(wchar_t);
671 CHECK_RANGES_OVERLAP("wcsncpy", to, from_size, from, from_size);
672 ASAN_READ_RANGE(ctx, from, from_size);
673 ASAN_WRITE_RANGE(ctx, to, size * sizeof(wchar_t));
674 }
675 return REAL(wcsncpy)(to, from, size);
676}
677
678template <typename Fn>
679static ALWAYS_INLINE auto StrtolImpl(void* ctx, Fn real, const char* nptr,
680 char** endptr, int base)
681 -> decltype(real(nullptr, nullptr, 0)) {
682 if (!flags()->replace_str)
683 return real(nptr, endptr, base);
684 char* real_endptr;
685 auto res = real(nptr, &real_endptr, base);
686 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
687 return res;
688}
689
690# define INTERCEPTOR_STRTO_BASE(ret_type, func) \
691 INTERCEPTOR(ret_type, func, const char* nptr, char** endptr, int base) { \
692 void* ctx; \
693 ASAN_INTERCEPTOR_ENTER(ctx, func); \
694 AsanInitFromRtl(); \
695 return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
696 }
697
698INTERCEPTOR_STRTO_BASE(long long, strtoll)
699
700# if SANITIZER_WINDOWS
701INTERCEPTOR(long, strtol, const char* nptr, char** endptr, int base) {
702 // REAL(strtol) may be ntdll!strtol, which doesn't set errno. Instead,
703 // call REAL(strtoll) and do the range check ourselves.
704 COMPILER_CHECK(sizeof(long) == sizeof(u32));
705
706 void* ctx;
707 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
708 AsanInitFromRtl();
709
710 long long result = StrtolImpl(ctx, REAL(strtoll), nptr, endptr, base);
711
712 if (result > INT32_MAX) {
713 errno = errno_ERANGE;
714 return INT32_MAX;
715 }
716 if (result < INT32_MIN) {
717 errno = errno_ERANGE;
718 return INT32_MIN;
719 }
720 return (long)result;
721}
722# else
723INTERCEPTOR_STRTO_BASE(long, strtol)
724# endif
725
726# if SANITIZER_GLIBC
727INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
728INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
729# endif
730
731INTERCEPTOR(int, atoi, const char* nptr) {
732 void* ctx;
733 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
734 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
735 return REAL(atoi)(nptr);
736 AsanInitFromRtl();
737 if (!flags()->replace_str) {
738 return REAL(atoi)(nptr);
739 }
740 char* real_endptr;
741 // "man atoi" tells that behavior of atoi(nptr) is the same as
742 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
743 // parsed integer can't be stored in *long* type (even if it's
744 // different from int). So, we just imitate this behavior.
745 int result = REAL(strtol)(nptr, &real_endptr, 10);
746 FixRealStrtolEndptr(nptr, endptr: &real_endptr);
747 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
748 return result;
749}
750
751INTERCEPTOR(long, atol, const char* nptr) {
752 void* ctx;
753 ASAN_INTERCEPTOR_ENTER(ctx, atol);
754 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
755 return REAL(atol)(nptr);
756 AsanInitFromRtl();
757 if (!flags()->replace_str) {
758 return REAL(atol)(nptr);
759 }
760 char* real_endptr;
761 long result = REAL(strtol)(nptr, &real_endptr, 10);
762 FixRealStrtolEndptr(nptr, endptr: &real_endptr);
763 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
764 return result;
765}
766
767INTERCEPTOR(long long, atoll, const char* nptr) {
768 void* ctx;
769 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
770 AsanInitFromRtl();
771 if (!flags()->replace_str) {
772 return REAL(atoll)(nptr);
773 }
774 char* real_endptr;
775 long long result = REAL(strtoll)(nptr, &real_endptr, 10);
776 FixRealStrtolEndptr(nptr, endptr: &real_endptr);
777 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
778 return result;
779}
780
781# if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
782static void AtCxaAtexit(void* unused) {
783 (void)unused;
784 StopInitOrderChecking();
785}
786# endif
787
788# if ASAN_INTERCEPT___CXA_ATEXIT
789INTERCEPTOR(int, __cxa_atexit, void (*func)(void*), void* arg,
790 void* dso_handle) {
791 if (SANITIZER_APPLE && UNLIKELY(!AsanInited()))
792 return REAL(__cxa_atexit)(func, arg, dso_handle);
793 AsanInitFromRtl();
794# if CAN_SANITIZE_LEAKS
795 __lsan::ScopedInterceptorDisabler disabler;
796# endif
797 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
798 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
799 return res;
800}
801# endif // ASAN_INTERCEPT___CXA_ATEXIT
802
803# if ASAN_INTERCEPT_ATEXIT
804INTERCEPTOR(int, atexit, void (*func)()) {
805 AsanInitFromRtl();
806# if CAN_SANITIZE_LEAKS
807 __lsan::ScopedInterceptorDisabler disabler;
808# endif
809 // Avoid calling real atexit as it is unreachable on at least on Linux.
810 int res = REAL(__cxa_atexit)((void (*)(void* a))func, nullptr, nullptr);
811 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
812 return res;
813}
814# endif
815
816# if ASAN_INTERCEPT_PTHREAD_ATFORK
817extern "C" {
818extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
819 void (*child)());
820}
821
822INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
823 void (*child)()) {
824# if CAN_SANITIZE_LEAKS
825 __lsan::ScopedInterceptorDisabler disabler;
826# endif
827 // REAL(pthread_atfork) cannot be called due to symbol indirections at least
828 // on NetBSD
829 return _pthread_atfork(prepare, parent, child);
830}
831# endif
832
833# if ASAN_INTERCEPT_VFORK
834DEFINE_REAL(int, vfork, )
835DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork, )
836# endif
837
838// ---------------------- InitializeAsanInterceptors ---------------- {{{1
839namespace __asan {
840void InitializeAsanInterceptors() {
841 static bool was_called_once;
842 CHECK(!was_called_once);
843 was_called_once = true;
844 InitializePlatformInterceptors();
845 InitializeCommonInterceptors();
846 InitializeSignalInterceptors();
847
848 // Intercept str* functions.
849 ASAN_INTERCEPT_FUNC(strcat);
850 ASAN_INTERCEPT_FUNC(strcpy);
851 ASAN_INTERCEPT_FUNC(strncat);
852 ASAN_INTERCEPT_FUNC(strncpy);
853 ASAN_INTERCEPT_FUNC(strdup);
854
855 // Intercept wcs* functions.
856 ASAN_INTERCEPT_FUNC(wcscpy);
857 ASAN_INTERCEPT_FUNC(wcsncpy);
858
859# if ASAN_INTERCEPT___STRDUP
860 ASAN_INTERCEPT_FUNC(__strdup);
861# endif
862# if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
863 ASAN_INTERCEPT_FUNC(index);
864# endif
865
866 ASAN_INTERCEPT_FUNC(atoi);
867 ASAN_INTERCEPT_FUNC(atol);
868 ASAN_INTERCEPT_FUNC(atoll);
869 ASAN_INTERCEPT_FUNC(strtol);
870 ASAN_INTERCEPT_FUNC(strtoll);
871# if SANITIZER_GLIBC
872 ASAN_INTERCEPT_FUNC(__isoc23_strtol);
873 ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
874# endif
875
876 // Intercept jump-related functions.
877# if ASAN_INTERCEPT_LONGJMP
878 ASAN_INTERCEPT_FUNC(longjmp);
879# endif
880
881# if ASAN_INTERCEPT_SWAPCONTEXT
882 ASAN_INTERCEPT_FUNC(swapcontext);
883 // See the makecontext interceptor above for an explanation.
884# if SANITIZER_SOLARIS && defined(__sparc__)
885 ASAN_INTERCEPT_FUNC(__makecontext_v2);
886# else
887 ASAN_INTERCEPT_FUNC(makecontext);
888# endif
889# endif
890# if ASAN_INTERCEPT__LONGJMP
891 ASAN_INTERCEPT_FUNC(_longjmp);
892# endif
893# if ASAN_INTERCEPT___LONGJMP_CHK
894 ASAN_INTERCEPT_FUNC(__longjmp_chk);
895# endif
896# if ASAN_INTERCEPT_SIGLONGJMP
897 ASAN_INTERCEPT_FUNC(siglongjmp);
898# endif
899
900 // Intercept exception handling functions.
901# if ASAN_INTERCEPT___CXA_THROW
902 ASAN_INTERCEPT_FUNC(__cxa_throw);
903# endif
904# if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
905 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
906# endif
907 // Indirectly intercept std::rethrow_exception.
908# if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
909 ASAN_INTERCEPT_FUNC(_Unwind_RaiseException);
910# endif
911 // Indirectly intercept std::rethrow_exception.
912# if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
913 ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException);
914# endif
915
916 // Intercept threading-related functions
917# if ASAN_INTERCEPT_PTHREAD_CREATE
918// TODO: this should probably have an unversioned fallback for newer arches?
919# if defined(ASAN_PTHREAD_CREATE_VERSION)
920 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
921# else
922 ASAN_INTERCEPT_FUNC(pthread_create);
923# endif
924 ASAN_INTERCEPT_FUNC(pthread_join);
925 ASAN_INTERCEPT_FUNC(pthread_detach);
926 ASAN_INTERCEPT_FUNC(pthread_exit);
927# endif
928
929# if ASAN_INTERCEPT_TIMEDJOIN
930 ASAN_INTERCEPT_FUNC(pthread_timedjoin_np);
931# endif
932
933# if ASAN_INTERCEPT_TRYJOIN
934 ASAN_INTERCEPT_FUNC(pthread_tryjoin_np);
935# endif
936
937 // Intercept atexit function.
938# if ASAN_INTERCEPT___CXA_ATEXIT
939 ASAN_INTERCEPT_FUNC(__cxa_atexit);
940# endif
941
942# if ASAN_INTERCEPT_ATEXIT
943 ASAN_INTERCEPT_FUNC(atexit);
944# endif
945
946# if ASAN_INTERCEPT_PTHREAD_ATFORK
947 ASAN_INTERCEPT_FUNC(pthread_atfork);
948# endif
949
950# if ASAN_INTERCEPT_VFORK
951 ASAN_INTERCEPT_FUNC(vfork);
952# endif
953
954 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
955}
956
957# if SANITIZER_WINDOWS
958# pragma pop_macro("strdup")
959# endif
960
961} // namespace __asan
962
963#endif // !SANITIZER_FUCHSIA
964