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