]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_interceptors.cc
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304149, and update
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_interceptors.cc
1 //===-- asan_interceptors.cc ----------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Intercept various libc functions.
13 //===----------------------------------------------------------------------===//
14
15 #include "asan_interceptors.h"
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 "lsan/lsan_common.h"
25 #include "sanitizer_common/sanitizer_libc.h"
26
27 #if SANITIZER_POSIX
28 #include "sanitizer_common/sanitizer_posix.h"
29 #endif
30
31 #if defined(__i386) && SANITIZER_LINUX
32 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
33 #elif defined(__mips__) && SANITIZER_LINUX
34 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
35 #endif
36
37 namespace __asan {
38
39 // Return true if we can quickly decide that the region is unpoisoned.
40 // We assume that a redzone is at least 16 bytes.
41 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
42   if (size == 0) return true;
43   if (size <= 32)
44     return !AddressIsPoisoned(beg) &&
45            !AddressIsPoisoned(beg + size - 1) &&
46            !AddressIsPoisoned(beg + size / 2);
47   if (size <= 64)
48     return !AddressIsPoisoned(beg) &&
49            !AddressIsPoisoned(beg + size / 4) &&
50            !AddressIsPoisoned(beg + size - 1) &&
51            !AddressIsPoisoned(beg + 3 * size / 4) &&
52            !AddressIsPoisoned(beg + size / 2);
53   return false;
54 }
55
56 struct AsanInterceptorContext {
57   const char *interceptor_name;
58 };
59
60 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
61 // and ASAN_WRITE_RANGE as macro instead of function so
62 // that no extra frames are created, and stack trace contains
63 // relevant information only.
64 // We check all shadow bytes.
65 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do {            \
66     uptr __offset = (uptr)(offset);                                     \
67     uptr __size = (uptr)(size);                                         \
68     uptr __bad = 0;                                                     \
69     if (__offset > __offset + __size) {                                 \
70       GET_STACK_TRACE_FATAL_HERE;                                       \
71       ReportStringFunctionSizeOverflow(__offset, __size, &stack);       \
72     }                                                                   \
73     if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
74         (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
75       AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx;     \
76       bool suppressed = false;                                          \
77       if (_ctx) {                                                       \
78         suppressed = IsInterceptorSuppressed(_ctx->interceptor_name);   \
79         if (!suppressed && HaveStackTraceBasedSuppressions()) {         \
80           GET_STACK_TRACE_FATAL_HERE;                                   \
81           suppressed = IsStackTraceSuppressed(&stack);                  \
82         }                                                               \
83       }                                                                 \
84       if (!suppressed) {                                                \
85         GET_CURRENT_PC_BP_SP;                                           \
86         ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
87       }                                                                 \
88     }                                                                   \
89   } while (0)
90
91 // memcpy is called during __asan_init() from the internals of printf(...).
92 // We do not treat memcpy with to==from as a bug.
93 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
94 #define ASAN_MEMCPY_IMPL(ctx, to, from, size)                           \
95   do {                                                                  \
96     if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
97     if (asan_init_is_running) {                                         \
98       return REAL(memcpy)(to, from, size);                              \
99     }                                                                   \
100     ENSURE_ASAN_INITED();                                               \
101     if (flags()->replace_intrin) {                                      \
102       if (to != from) {                                                 \
103         CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);           \
104       }                                                                 \
105       ASAN_READ_RANGE(ctx, from, size);                                 \
106       ASAN_WRITE_RANGE(ctx, to, size);                                  \
107     }                                                                   \
108     return REAL(memcpy)(to, from, size);                                \
109   } while (0)
110
111 // memset is called inside Printf.
112 #define ASAN_MEMSET_IMPL(ctx, block, c, size)                           \
113   do {                                                                  \
114     if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
115     if (asan_init_is_running) {                                         \
116       return REAL(memset)(block, c, size);                              \
117     }                                                                   \
118     ENSURE_ASAN_INITED();                                               \
119     if (flags()->replace_intrin) {                                      \
120       ASAN_WRITE_RANGE(ctx, block, size);                               \
121     }                                                                   \
122     return REAL(memset)(block, c, size);                                \
123   } while (0)
124
125 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size)                           \
126   do {                                                                   \
127     if (UNLIKELY(!asan_inited)) return internal_memmove(to, from, size); \
128     ENSURE_ASAN_INITED();                                                \
129     if (flags()->replace_intrin) {                                       \
130       ASAN_READ_RANGE(ctx, from, size);                                  \
131       ASAN_WRITE_RANGE(ctx, to, size);                                   \
132     }                                                                    \
133     return internal_memmove(to, from, size);                             \
134   } while (0)
135
136 #define ASAN_READ_RANGE(ctx, offset, size) \
137   ACCESS_MEMORY_RANGE(ctx, offset, size, false)
138 #define ASAN_WRITE_RANGE(ctx, offset, size) \
139   ACCESS_MEMORY_RANGE(ctx, offset, size, true)
140
141 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \
142   ASAN_READ_RANGE((ctx), (s),                                   \
143     common_flags()->strict_string_checks ? (len) + 1 : (n))
144
145 #define ASAN_READ_STRING(ctx, s, n)                             \
146   ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
147
148 // Behavior of functions like "memcpy" or "strcpy" is undefined
149 // if memory intervals overlap. We report error in this case.
150 // Macro is used to avoid creation of new frames.
151 static inline bool RangesOverlap(const char *offset1, uptr length1,
152                                  const char *offset2, uptr length2) {
153   return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
154 }
155 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
156   const char *offset1 = (const char*)_offset1; \
157   const char *offset2 = (const char*)_offset2; \
158   if (RangesOverlap(offset1, length1, offset2, length2)) { \
159     GET_STACK_TRACE_FATAL_HERE; \
160     ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
161                                             offset2, length2, &stack); \
162   } \
163 } while (0)
164
165 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
166 #if SANITIZER_INTERCEPT_STRNLEN
167   if (REAL(strnlen)) {
168     return REAL(strnlen)(s, maxlen);
169   }
170 #endif
171   return internal_strnlen(s, maxlen);
172 }
173
174 void SetThreadName(const char *name) {
175   AsanThread *t = GetCurrentThread();
176   if (t)
177     asanThreadRegistry().SetThreadName(t->tid(), name);
178 }
179
180 int OnExit() {
181   // FIXME: ask frontend whether we need to return failure.
182   return 0;
183 }
184
185 } // namespace __asan
186
187 // ---------------------- Wrappers ---------------- {{{1
188 using namespace __asan;  // NOLINT
189
190 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
191 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
192
193 #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
194   AsanInterceptorContext _ctx = {#func};                                       \
195   ctx = (void *)&_ctx;                                                         \
196   (void) ctx;                                                                  \
197
198 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
199 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
200   ASAN_INTERCEPT_FUNC_VER(name, ver)
201 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
202   ASAN_WRITE_RANGE(ctx, ptr, size)
203 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
204   ASAN_READ_RANGE(ctx, ptr, size)
205 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
206   ASAN_INTERCEPTOR_ENTER(ctx, func);                                           \
207   do {                                                                         \
208     if (asan_init_is_running)                                                  \
209       return REAL(func)(__VA_ARGS__);                                          \
210     if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
211       return REAL(func)(__VA_ARGS__);                                          \
212     ENSURE_ASAN_INITED();                                                      \
213   } while (false)
214 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
215   do {                                            \
216   } while (false)
217 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
218   do {                                         \
219   } while (false)
220 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
221   do {                                         \
222   } while (false)
223 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
224   do {                                                      \
225   } while (false)
226 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
227 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
228 // But asan does not remember UserId's for threads (pthread_t);
229 // and remembers all ever existed threads, so the linear search by UserId
230 // can be slow.
231 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
232   do {                                                         \
233   } while (false)
234 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
235 // Strict init-order checking is dlopen-hostile:
236 // https://github.com/google/sanitizers/issues/178
237 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
238   do {                                                                         \
239     if (flags()->strict_init_order)                                            \
240       StopInitOrderChecking();                                                 \
241     CheckNoDeepBind(filename, flag);                                           \
242   } while (false)
243 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
244 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
245   CoverageUpdateMapping()
246 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
247 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
248 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
249   if (AsanThread *t = GetCurrentThread()) {                                    \
250     *begin = t->tls_begin();                                                   \
251     *end = t->tls_end();                                                       \
252   } else {                                                                     \
253     *begin = *end = 0;                                                         \
254   }
255
256 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
257   do {                                                       \
258     ASAN_INTERCEPTOR_ENTER(ctx, memmove);                    \
259     ASAN_MEMMOVE_IMPL(ctx, to, from, size);                  \
260   } while (false)
261
262 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
263   do {                                                      \
264     ASAN_INTERCEPTOR_ENTER(ctx, memcpy);                    \
265     ASAN_MEMCPY_IMPL(ctx, to, from, size);                  \
266   } while (false)
267
268 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
269   do {                                                      \
270     ASAN_INTERCEPTOR_ENTER(ctx, memset);                    \
271     ASAN_MEMSET_IMPL(ctx, block, c, size);                  \
272   } while (false)
273
274 #include "sanitizer_common/sanitizer_common_interceptors.inc"
275
276 // Syscall interceptors don't have contexts, we don't support suppressions
277 // for them.
278 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
279 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
280 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
281   do {                                       \
282     (void)(p);                               \
283     (void)(s);                               \
284   } while (false)
285 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
286   do {                                        \
287     (void)(p);                                \
288     (void)(s);                                \
289   } while (false)
290 #include "sanitizer_common/sanitizer_common_syscalls.inc"
291
292 struct ThreadStartParam {
293   atomic_uintptr_t t;
294   atomic_uintptr_t is_registered;
295 };
296
297 #if ASAN_INTERCEPT_PTHREAD_CREATE
298 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
299   ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
300   AsanThread *t = nullptr;
301   while ((t = reinterpret_cast<AsanThread *>(
302               atomic_load(&param->t, memory_order_acquire))) == nullptr)
303     internal_sched_yield();
304   SetCurrentThread(t);
305   return t->ThreadStart(GetTid(), &param->is_registered);
306 }
307
308 INTERCEPTOR(int, pthread_create, void *thread,
309     void *attr, void *(*start_routine)(void*), void *arg) {
310   EnsureMainThreadIDIsCorrect();
311   // Strict init-order checking is thread-hostile.
312   if (flags()->strict_init_order)
313     StopInitOrderChecking();
314   GET_STACK_TRACE_THREAD;
315   int detached = 0;
316   if (attr)
317     REAL(pthread_attr_getdetachstate)(attr, &detached);
318   ThreadStartParam param;
319   atomic_store(&param.t, 0, memory_order_relaxed);
320   atomic_store(&param.is_registered, 0, memory_order_relaxed);
321   int result;
322   {
323     // Ignore all allocations made by pthread_create: thread stack/TLS may be
324     // stored by pthread for future reuse even after thread destruction, and
325     // the linked list it's stored in doesn't even hold valid pointers to the
326     // objects, the latter are calculated by obscure pointer arithmetic.
327 #if CAN_SANITIZE_LEAKS
328     __lsan::ScopedInterceptorDisabler disabler;
329 #endif
330     result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
331   }
332   if (result == 0) {
333     u32 current_tid = GetCurrentTidOrInvalid();
334     AsanThread *t =
335         AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
336     atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
337     // Wait until the AsanThread object is initialized and the ThreadRegistry
338     // entry is in "started" state. One reason for this is that after this
339     // interceptor exits, the child thread's stack may be the only thing holding
340     // the |arg| pointer. This may cause LSan to report a leak if leak checking
341     // happens at a point when the interceptor has already exited, but the stack
342     // range for the child thread is not yet known.
343     while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
344       internal_sched_yield();
345   }
346   return result;
347 }
348
349 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
350   return real_pthread_join(t, arg);
351 }
352
353 DEFINE_REAL_PTHREAD_FUNCTIONS
354 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
355
356 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
357
358 #if SANITIZER_ANDROID
359 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
360   if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
361     return REAL(bsd_signal)(signum, handler);
362   return 0;
363 }
364 #endif
365
366 INTERCEPTOR(void*, signal, int signum, void *handler) {
367   if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
368     return REAL(signal)(signum, handler);
369   return nullptr;
370 }
371
372 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
373                             struct sigaction *oldact) {
374   if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
375     return REAL(sigaction)(signum, act, oldact);
376   return 0;
377 }
378
379 namespace __sanitizer {
380 int real_sigaction(int signum, const void *act, void *oldact) {
381   return REAL(sigaction)(signum, (const struct sigaction *)act,
382                          (struct sigaction *)oldact);
383 }
384 } // namespace __sanitizer
385
386 #elif SANITIZER_POSIX
387 // We need to have defined REAL(sigaction) on posix systems.
388 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
389     struct sigaction *oldact)
390 #endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
391
392 #if ASAN_INTERCEPT_SWAPCONTEXT
393 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
394   // Align to page size.
395   uptr PageSize = GetPageSizeCached();
396   uptr bottom = stack & ~(PageSize - 1);
397   ssize += stack - bottom;
398   ssize = RoundUpTo(ssize, PageSize);
399   static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
400   if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
401     PoisonShadow(bottom, ssize, 0);
402   }
403 }
404
405 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
406             struct ucontext_t *ucp) {
407   static bool reported_warning = false;
408   if (!reported_warning) {
409     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
410            "functions and may produce false positives in some cases!\n");
411     reported_warning = true;
412   }
413   // Clear shadow memory for new context (it may share stack
414   // with current context).
415   uptr stack, ssize;
416   ReadContextStack(ucp, &stack, &ssize);
417   ClearShadowMemoryForContextStack(stack, ssize);
418   int res = REAL(swapcontext)(oucp, ucp);
419   // swapcontext technically does not return, but program may swap context to
420   // "oucp" later, that would look as if swapcontext() returned 0.
421   // We need to clear shadow for ucp once again, as it may be in arbitrary
422   // state.
423   ClearShadowMemoryForContextStack(stack, ssize);
424   return res;
425 }
426 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
427
428 INTERCEPTOR(void, longjmp, void *env, int val) {
429   __asan_handle_no_return();
430   REAL(longjmp)(env, val);
431 }
432
433 #if ASAN_INTERCEPT__LONGJMP
434 INTERCEPTOR(void, _longjmp, void *env, int val) {
435   __asan_handle_no_return();
436   REAL(_longjmp)(env, val);
437 }
438 #endif
439
440 #if ASAN_INTERCEPT___LONGJMP_CHK
441 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
442   __asan_handle_no_return();
443   REAL(__longjmp_chk)(env, val);
444 }
445 #endif
446
447 #if ASAN_INTERCEPT_SIGLONGJMP
448 INTERCEPTOR(void, siglongjmp, void *env, int val) {
449   __asan_handle_no_return();
450   REAL(siglongjmp)(env, val);
451 }
452 #endif
453
454 #if ASAN_INTERCEPT___CXA_THROW
455 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
456   CHECK(REAL(__cxa_throw));
457   __asan_handle_no_return();
458   REAL(__cxa_throw)(a, b, c);
459 }
460 #endif
461
462 void *__asan_memcpy(void *to, const void *from, uptr size) {
463   ASAN_MEMCPY_IMPL(nullptr, to, from, size);
464 }
465
466 void *__asan_memset(void *block, int c, uptr size) {
467   ASAN_MEMSET_IMPL(nullptr, block, c, size);
468 }
469
470 void *__asan_memmove(void *to, const void *from, uptr size) {
471   ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
472 }
473
474 #if ASAN_INTERCEPT_INDEX
475 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
476 INTERCEPTOR(char*, index, const char *string, int c)
477   ALIAS(WRAPPER_NAME(strchr));
478 # else
479 #  if SANITIZER_MAC
480 DECLARE_REAL(char*, index, const char *string, int c)
481 OVERRIDE_FUNCTION(index, strchr);
482 #  else
483 DEFINE_REAL(char*, index, const char *string, int c)
484 #  endif
485 # endif
486 #endif  // ASAN_INTERCEPT_INDEX
487
488 // For both strcat() and strncat() we need to check the validity of |to|
489 // argument irrespective of the |from| length.
490 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
491   void *ctx;
492   ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
493   ENSURE_ASAN_INITED();
494   if (flags()->replace_str) {
495     uptr from_length = REAL(strlen)(from);
496     ASAN_READ_RANGE(ctx, from, from_length + 1);
497     uptr to_length = REAL(strlen)(to);
498     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
499     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
500     // If the copying actually happens, the |from| string should not overlap
501     // with the resulting string starting at |to|, which has a length of
502     // to_length + from_length + 1.
503     if (from_length > 0) {
504       CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
505                            from, from_length + 1);
506     }
507   }
508   return REAL(strcat)(to, from);  // NOLINT
509 }
510
511 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
512   void *ctx;
513   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
514   ENSURE_ASAN_INITED();
515   if (flags()->replace_str) {
516     uptr from_length = MaybeRealStrnlen(from, size);
517     uptr copy_length = Min(size, from_length + 1);
518     ASAN_READ_RANGE(ctx, from, copy_length);
519     uptr to_length = REAL(strlen)(to);
520     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
521     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
522     if (from_length > 0) {
523       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
524                            from, copy_length);
525     }
526   }
527   return REAL(strncat)(to, from, size);
528 }
529
530 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
531   void *ctx;
532   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
533 #if SANITIZER_MAC
534   if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
535 #endif
536   // strcpy is called from malloc_default_purgeable_zone()
537   // in __asan::ReplaceSystemAlloc() on Mac.
538   if (asan_init_is_running) {
539     return REAL(strcpy)(to, from);  // NOLINT
540   }
541   ENSURE_ASAN_INITED();
542   if (flags()->replace_str) {
543     uptr from_size = REAL(strlen)(from) + 1;
544     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
545     ASAN_READ_RANGE(ctx, from, from_size);
546     ASAN_WRITE_RANGE(ctx, to, from_size);
547   }
548   return REAL(strcpy)(to, from);  // NOLINT
549 }
550
551 INTERCEPTOR(char*, strdup, const char *s) {
552   void *ctx;
553   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
554   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
555   ENSURE_ASAN_INITED();
556   uptr length = REAL(strlen)(s);
557   if (flags()->replace_str) {
558     ASAN_READ_RANGE(ctx, s, length + 1);
559   }
560   GET_STACK_TRACE_MALLOC;
561   void *new_mem = asan_malloc(length + 1, &stack);
562   REAL(memcpy)(new_mem, s, length + 1);
563   return reinterpret_cast<char*>(new_mem);
564 }
565
566 #if ASAN_INTERCEPT___STRDUP
567 INTERCEPTOR(char*, __strdup, const char *s) {
568   void *ctx;
569   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
570   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
571   ENSURE_ASAN_INITED();
572   uptr length = REAL(strlen)(s);
573   if (flags()->replace_str) {
574     ASAN_READ_RANGE(ctx, s, length + 1);
575   }
576   GET_STACK_TRACE_MALLOC;
577   void *new_mem = asan_malloc(length + 1, &stack);
578   REAL(memcpy)(new_mem, s, length + 1);
579   return reinterpret_cast<char*>(new_mem);
580 }
581 #endif // ASAN_INTERCEPT___STRDUP
582
583 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
584   void *ctx;
585   ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
586   SIZE_T length = internal_wcslen(s);
587   if (!asan_init_is_running) {
588     ENSURE_ASAN_INITED();
589     ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
590   }
591   return length;
592 }
593
594 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
595   void *ctx;
596   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
597   ENSURE_ASAN_INITED();
598   if (flags()->replace_str) {
599     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
600     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
601     ASAN_READ_RANGE(ctx, from, from_size);
602     ASAN_WRITE_RANGE(ctx, to, size);
603   }
604   return REAL(strncpy)(to, from, size);
605 }
606
607 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
608             char **endptr, int base) {
609   void *ctx;
610   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
611   ENSURE_ASAN_INITED();
612   if (!flags()->replace_str) {
613     return REAL(strtol)(nptr, endptr, base);
614   }
615   char *real_endptr;
616   long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
617   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
618   return result;
619 }
620
621 INTERCEPTOR(int, atoi, const char *nptr) {
622   void *ctx;
623   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
624 #if SANITIZER_MAC
625   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
626 #endif
627   ENSURE_ASAN_INITED();
628   if (!flags()->replace_str) {
629     return REAL(atoi)(nptr);
630   }
631   char *real_endptr;
632   // "man atoi" tells that behavior of atoi(nptr) is the same as
633   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
634   // parsed integer can't be stored in *long* type (even if it's
635   // different from int). So, we just imitate this behavior.
636   int result = REAL(strtol)(nptr, &real_endptr, 10);
637   FixRealStrtolEndptr(nptr, &real_endptr);
638   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
639   return result;
640 }
641
642 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
643   void *ctx;
644   ASAN_INTERCEPTOR_ENTER(ctx, atol);
645 #if SANITIZER_MAC
646   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
647 #endif
648   ENSURE_ASAN_INITED();
649   if (!flags()->replace_str) {
650     return REAL(atol)(nptr);
651   }
652   char *real_endptr;
653   long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
654   FixRealStrtolEndptr(nptr, &real_endptr);
655   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
656   return result;
657 }
658
659 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
660 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
661             char **endptr, int base) {
662   void *ctx;
663   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
664   ENSURE_ASAN_INITED();
665   if (!flags()->replace_str) {
666     return REAL(strtoll)(nptr, endptr, base);
667   }
668   char *real_endptr;
669   long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
670   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
671   return result;
672 }
673
674 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
675   void *ctx;
676   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
677   ENSURE_ASAN_INITED();
678   if (!flags()->replace_str) {
679     return REAL(atoll)(nptr);
680   }
681   char *real_endptr;
682   long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
683   FixRealStrtolEndptr(nptr, &real_endptr);
684   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
685   return result;
686 }
687 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
688
689 #if ASAN_INTERCEPT___CXA_ATEXIT
690 static void AtCxaAtexit(void *unused) {
691   (void)unused;
692   StopInitOrderChecking();
693 }
694
695 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
696             void *dso_handle) {
697 #if SANITIZER_MAC
698   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
699 #endif
700   ENSURE_ASAN_INITED();
701   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
702   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
703   return res;
704 }
705 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
706
707 #if ASAN_INTERCEPT_FORK
708 INTERCEPTOR(int, fork, void) {
709   ENSURE_ASAN_INITED();
710   if (common_flags()->coverage) CovBeforeFork();
711   int pid = REAL(fork)();
712   if (common_flags()->coverage) CovAfterFork(pid);
713   return pid;
714 }
715 #endif  // ASAN_INTERCEPT_FORK
716
717 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
718 namespace __asan {
719 void InitializeAsanInterceptors() {
720   static bool was_called_once;
721   CHECK(!was_called_once);
722   was_called_once = true;
723   InitializeCommonInterceptors();
724
725   // Intercept str* functions.
726   ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
727   ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
728   ASAN_INTERCEPT_FUNC(wcslen);
729   ASAN_INTERCEPT_FUNC(strncat);
730   ASAN_INTERCEPT_FUNC(strncpy);
731   ASAN_INTERCEPT_FUNC(strdup);
732 #if ASAN_INTERCEPT___STRDUP
733   ASAN_INTERCEPT_FUNC(__strdup);
734 #endif
735 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
736   ASAN_INTERCEPT_FUNC(index);
737 #endif
738
739   ASAN_INTERCEPT_FUNC(atoi);
740   ASAN_INTERCEPT_FUNC(atol);
741   ASAN_INTERCEPT_FUNC(strtol);
742 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
743   ASAN_INTERCEPT_FUNC(atoll);
744   ASAN_INTERCEPT_FUNC(strtoll);
745 #endif
746
747   // Intecept signal- and jump-related functions.
748   ASAN_INTERCEPT_FUNC(longjmp);
749 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
750   ASAN_INTERCEPT_FUNC(sigaction);
751 #if SANITIZER_ANDROID
752   ASAN_INTERCEPT_FUNC(bsd_signal);
753 #endif
754   ASAN_INTERCEPT_FUNC(signal);
755 #endif
756 #if ASAN_INTERCEPT_SWAPCONTEXT
757   ASAN_INTERCEPT_FUNC(swapcontext);
758 #endif
759 #if ASAN_INTERCEPT__LONGJMP
760   ASAN_INTERCEPT_FUNC(_longjmp);
761 #endif
762 #if ASAN_INTERCEPT___LONGJMP_CHK
763   ASAN_INTERCEPT_FUNC(__longjmp_chk);
764 #endif
765 #if ASAN_INTERCEPT_SIGLONGJMP
766   ASAN_INTERCEPT_FUNC(siglongjmp);
767 #endif
768
769   // Intercept exception handling functions.
770 #if ASAN_INTERCEPT___CXA_THROW
771   ASAN_INTERCEPT_FUNC(__cxa_throw);
772 #endif
773
774   // Intercept threading-related functions
775 #if ASAN_INTERCEPT_PTHREAD_CREATE
776 #if defined(ASAN_PTHREAD_CREATE_VERSION)
777   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
778 #else
779   ASAN_INTERCEPT_FUNC(pthread_create);
780 #endif
781   ASAN_INTERCEPT_FUNC(pthread_join);
782 #endif
783
784   // Intercept atexit function.
785 #if ASAN_INTERCEPT___CXA_ATEXIT
786   ASAN_INTERCEPT_FUNC(__cxa_atexit);
787 #endif
788
789 #if ASAN_INTERCEPT_FORK
790   ASAN_INTERCEPT_FUNC(fork);
791 #endif
792
793   InitializePlatformInterceptors();
794
795   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
796 }
797
798 } // namespace __asan