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