asan_interceptors.cc revision 1b057b20db71ec6cc2bac460c8b2848f0889d47d
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_report.h"
21#include "asan_stack.h"
22#include "asan_stats.h"
23#include "asan_thread_registry.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 = asanThreadRegistry().GetCurrent();
93  if (t)
94    t->summary()->set_name(name);
95}
96
97}  // namespace __asan
98
99// ---------------------- Wrappers ---------------- {{{1
100using namespace __asan;  // NOLINT
101
102#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
103  ASAN_WRITE_RANGE(ptr, size)
104#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
105#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
106  do {                                           \
107    ctx = 0;                                     \
108    (void)ctx;                                   \
109    ENSURE_ASAN_INITED();                        \
110  } while (false)
111#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
112#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
113#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
114#include "sanitizer_common/sanitizer_common_interceptors.inc"
115
116static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
117  AsanThread *t = (AsanThread*)arg;
118  asanThreadRegistry().SetCurrent(t);
119  return t->ThreadStart();
120}
121
122#if ASAN_INTERCEPT_PTHREAD_CREATE
123INTERCEPTOR(int, pthread_create, void *thread,
124    void *attr, void *(*start_routine)(void*), void *arg) {
125  GET_STACK_TRACE_THREAD;
126  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
127  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
128  asanThreadRegistry().RegisterThread(t);
129  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
130}
131#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
132
133#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
134INTERCEPTOR(void*, signal, int signum, void *handler) {
135  if (!AsanInterceptsSignal(signum)) {
136    return REAL(signal)(signum, handler);
137  }
138  return 0;
139}
140
141INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
142                            struct sigaction *oldact) {
143  if (!AsanInterceptsSignal(signum)) {
144    return REAL(sigaction)(signum, act, oldact);
145  }
146  return 0;
147}
148#elif ASAN_POSIX
149// We need to have defined REAL(sigaction) on posix systems.
150DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
151    struct sigaction *oldact);
152#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
153
154#if ASAN_INTERCEPT_SWAPCONTEXT
155static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
156  // Align to page size.
157  uptr PageSize = GetPageSizeCached();
158  uptr bottom = stack & ~(PageSize - 1);
159  ssize += stack - bottom;
160  ssize = RoundUpTo(ssize, PageSize);
161  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
162  if (ssize && ssize <= kMaxSaneContextStackSize) {
163    PoisonShadow(bottom, ssize, 0);
164  }
165}
166
167INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
168            struct ucontext_t *ucp) {
169  static bool reported_warning = false;
170  if (!reported_warning) {
171    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
172           "functions and may produce false positives in some cases!\n");
173    reported_warning = true;
174  }
175  // Clear shadow memory for new context (it may share stack
176  // with current context).
177  uptr stack, ssize;
178  ReadContextStack(ucp, &stack, &ssize);
179  ClearShadowMemoryForContextStack(stack, ssize);
180  int res = REAL(swapcontext)(oucp, ucp);
181  // swapcontext technically does not return, but program may swap context to
182  // "oucp" later, that would look as if swapcontext() returned 0.
183  // We need to clear shadow for ucp once again, as it may be in arbitrary
184  // state.
185  ClearShadowMemoryForContextStack(stack, ssize);
186  return res;
187}
188#endif  // ASAN_INTERCEPT_SWAPCONTEXT
189
190INTERCEPTOR(void, longjmp, void *env, int val) {
191  __asan_handle_no_return();
192  REAL(longjmp)(env, val);
193}
194
195#if ASAN_INTERCEPT__LONGJMP
196INTERCEPTOR(void, _longjmp, void *env, int val) {
197  __asan_handle_no_return();
198  REAL(_longjmp)(env, val);
199}
200#endif
201
202#if ASAN_INTERCEPT_SIGLONGJMP
203INTERCEPTOR(void, siglongjmp, void *env, int val) {
204  __asan_handle_no_return();
205  REAL(siglongjmp)(env, val);
206}
207#endif
208
209#if ASAN_INTERCEPT___CXA_THROW
210INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
211  CHECK(REAL(__cxa_throw));
212  __asan_handle_no_return();
213  REAL(__cxa_throw)(a, b, c);
214}
215#endif
216
217// intercept mlock and friends.
218// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
219// All functions return 0 (success).
220static void MlockIsUnsupported() {
221  static bool printed = 0;
222  if (printed) return;
223  printed = true;
224  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
225}
226
227extern "C" {
228INTERCEPTOR(int, mlock, const void *addr, uptr len) {
229  MlockIsUnsupported();
230  return 0;
231}
232
233INTERCEPTOR(int, munlock, const void *addr, uptr len) {
234  MlockIsUnsupported();
235  return 0;
236}
237
238INTERCEPTOR(int, mlockall, int flags) {
239  MlockIsUnsupported();
240  return 0;
241}
242
243INTERCEPTOR(int, munlockall, void) {
244  MlockIsUnsupported();
245  return 0;
246}
247}  // extern "C"
248
249static inline int CharCmp(unsigned char c1, unsigned char c2) {
250  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
251}
252
253static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
254  int c1_low = ToLower(c1);
255  int c2_low = ToLower(c2);
256  return c1_low - c2_low;
257}
258
259INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
260  if (!asan_inited) return internal_memcmp(a1, a2, size);
261  ENSURE_ASAN_INITED();
262  if (flags()->replace_intrin) {
263    // We check the entire regions even if the first bytes of the buffers
264    // are different.
265    ASAN_READ_RANGE(a1, size);
266    ASAN_READ_RANGE(a2, size);
267  }
268  return REAL(memcmp(a1, a2, size));
269}
270
271INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
272  if (!asan_inited) return internal_memcpy(to, from, size);
273  // memcpy is called during __asan_init() from the internals
274  // of printf(...).
275  if (asan_init_is_running) {
276    return REAL(memcpy)(to, from, size);
277  }
278  ENSURE_ASAN_INITED();
279  if (flags()->replace_intrin) {
280    if (to != from) {
281      // We do not treat memcpy with to==from as a bug.
282      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
283      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
284    }
285    ASAN_READ_RANGE(from, size);
286    ASAN_WRITE_RANGE(to, size);
287  }
288  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
289  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
290  return internal_memcpy(to, from, size);
291}
292
293INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
294  if (!asan_inited) return internal_memmove(to, from, size);
295  if (asan_init_is_running) {
296    return REAL(memmove)(to, from, size);
297  }
298  ENSURE_ASAN_INITED();
299  if (flags()->replace_intrin) {
300    ASAN_READ_RANGE(from, size);
301    ASAN_WRITE_RANGE(to, size);
302  }
303  // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
304  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
305  return internal_memmove(to, from, size);
306}
307
308INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
309  if (!asan_inited) return internal_memset(block, c, size);
310  // memset is called inside Printf.
311  if (asan_init_is_running) {
312    return REAL(memset)(block, c, size);
313  }
314  ENSURE_ASAN_INITED();
315  if (flags()->replace_intrin) {
316    ASAN_WRITE_RANGE(block, size);
317  }
318  return REAL(memset)(block, c, size);
319}
320
321INTERCEPTOR(char*, strchr, const char *str, int c) {
322  if (!asan_inited) return internal_strchr(str, c);
323  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
324  // used.
325  if (asan_init_is_running) {
326    return REAL(strchr)(str, c);
327  }
328  ENSURE_ASAN_INITED();
329  char *result = REAL(strchr)(str, c);
330  if (flags()->replace_str) {
331    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
332    ASAN_READ_RANGE(str, bytes_read);
333  }
334  return result;
335}
336
337#if ASAN_INTERCEPT_INDEX
338# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
339INTERCEPTOR(char*, index, const char *string, int c)
340  ALIAS(WRAPPER_NAME(strchr));
341# else
342#  if defined(__APPLE__)
343DECLARE_REAL(char*, index, const char *string, int c)
344OVERRIDE_FUNCTION(index, strchr);
345#  else
346DEFINE_REAL(char*, index, const char *string, int c);
347#  endif
348# endif
349#endif  // ASAN_INTERCEPT_INDEX
350
351// For both strcat() and strncat() we need to check the validity of |to|
352// argument irrespective of the |from| length.
353INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
354  ENSURE_ASAN_INITED();
355  if (flags()->replace_str) {
356    uptr from_length = REAL(strlen)(from);
357    ASAN_READ_RANGE(from, from_length + 1);
358    uptr to_length = REAL(strlen)(to);
359    ASAN_READ_RANGE(to, to_length);
360    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
361    // If the copying actually happens, the |from| string should not overlap
362    // with the resulting string starting at |to|, which has a length of
363    // to_length + from_length + 1.
364    if (from_length > 0) {
365      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
366                           from, from_length + 1);
367    }
368  }
369  return REAL(strcat)(to, from);  // NOLINT
370}
371
372INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
373  ENSURE_ASAN_INITED();
374  if (flags()->replace_str) {
375    uptr from_length = MaybeRealStrnlen(from, size);
376    uptr copy_length = Min(size, from_length + 1);
377    ASAN_READ_RANGE(from, copy_length);
378    uptr to_length = REAL(strlen)(to);
379    ASAN_READ_RANGE(to, to_length);
380    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
381    if (from_length > 0) {
382      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
383                           from, copy_length);
384    }
385  }
386  return REAL(strncat)(to, from, size);
387}
388
389INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
390  if (!asan_inited) return internal_strcmp(s1, s2);
391  if (asan_init_is_running) {
392    return REAL(strcmp)(s1, s2);
393  }
394  ENSURE_ASAN_INITED();
395  unsigned char c1, c2;
396  uptr i;
397  for (i = 0; ; i++) {
398    c1 = (unsigned char)s1[i];
399    c2 = (unsigned char)s2[i];
400    if (c1 != c2 || c1 == '\0') break;
401  }
402  ASAN_READ_RANGE(s1, i + 1);
403  ASAN_READ_RANGE(s2, i + 1);
404  return CharCmp(c1, c2);
405}
406
407INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
408#if defined(__APPLE__)
409  if (!asan_inited) return REAL(strcpy)(to, from);  // NOLINT
410#endif
411  // strcpy is called from malloc_default_purgeable_zone()
412  // in __asan::ReplaceSystemAlloc() on Mac.
413  if (asan_init_is_running) {
414    return REAL(strcpy)(to, from);  // NOLINT
415  }
416  ENSURE_ASAN_INITED();
417  if (flags()->replace_str) {
418    uptr from_size = REAL(strlen)(from) + 1;
419    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
420    ASAN_READ_RANGE(from, from_size);
421    ASAN_WRITE_RANGE(to, from_size);
422  }
423  return REAL(strcpy)(to, from);  // NOLINT
424}
425
426#if ASAN_INTERCEPT_STRDUP
427INTERCEPTOR(char*, strdup, const char *s) {
428#if defined(__APPLE__)
429  // FIXME: because internal_strdup() uses InternalAlloc(), which currently
430  // just calls malloc() on Mac, we can't use internal_strdup() with the
431  // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
432  // starts using mmap() instead.
433  // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
434  if (!asan_inited) return REAL(strdup)(s);
435#endif
436  if (!asan_inited) return internal_strdup(s);
437  ENSURE_ASAN_INITED();
438  if (flags()->replace_str) {
439    uptr length = REAL(strlen)(s);
440    ASAN_READ_RANGE(s, length + 1);
441  }
442  return REAL(strdup)(s);
443}
444#endif
445
446INTERCEPTOR(uptr, strlen, const char *s) {
447  if (!asan_inited) return internal_strlen(s);
448  // strlen is called from malloc_default_purgeable_zone()
449  // in __asan::ReplaceSystemAlloc() on Mac.
450  if (asan_init_is_running) {
451    return REAL(strlen)(s);
452  }
453  ENSURE_ASAN_INITED();
454  uptr length = REAL(strlen)(s);
455  if (flags()->replace_str) {
456    ASAN_READ_RANGE(s, length + 1);
457  }
458  return length;
459}
460
461#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
462INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
463  ENSURE_ASAN_INITED();
464  unsigned char c1, c2;
465  uptr i;
466  for (i = 0; ; i++) {
467    c1 = (unsigned char)s1[i];
468    c2 = (unsigned char)s2[i];
469    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
470  }
471  ASAN_READ_RANGE(s1, i + 1);
472  ASAN_READ_RANGE(s2, i + 1);
473  return CharCaseCmp(c1, c2);
474}
475
476INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
477  ENSURE_ASAN_INITED();
478  unsigned char c1 = 0, c2 = 0;
479  uptr i;
480  for (i = 0; i < n; i++) {
481    c1 = (unsigned char)s1[i];
482    c2 = (unsigned char)s2[i];
483    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
484  }
485  ASAN_READ_RANGE(s1, Min(i + 1, n));
486  ASAN_READ_RANGE(s2, Min(i + 1, n));
487  return CharCaseCmp(c1, c2);
488}
489#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
490
491INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
492  if (!asan_inited) return internal_strncmp(s1, s2, size);
493  // strncmp is called from malloc_default_purgeable_zone()
494  // in __asan::ReplaceSystemAlloc() on Mac.
495  if (asan_init_is_running) {
496    return REAL(strncmp)(s1, s2, size);
497  }
498  ENSURE_ASAN_INITED();
499  unsigned char c1 = 0, c2 = 0;
500  uptr i;
501  for (i = 0; i < size; i++) {
502    c1 = (unsigned char)s1[i];
503    c2 = (unsigned char)s2[i];
504    if (c1 != c2 || c1 == '\0') break;
505  }
506  ASAN_READ_RANGE(s1, Min(i + 1, size));
507  ASAN_READ_RANGE(s2, Min(i + 1, size));
508  return CharCmp(c1, c2);
509}
510
511INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
512  ENSURE_ASAN_INITED();
513  if (flags()->replace_str) {
514    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
515    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
516    ASAN_READ_RANGE(from, from_size);
517    ASAN_WRITE_RANGE(to, size);
518  }
519  return REAL(strncpy)(to, from, size);
520}
521
522#if ASAN_INTERCEPT_STRNLEN
523INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
524  ENSURE_ASAN_INITED();
525  uptr length = REAL(strnlen)(s, maxlen);
526  if (flags()->replace_str) {
527    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
528  }
529  return length;
530}
531#endif  // ASAN_INTERCEPT_STRNLEN
532
533static inline bool IsValidStrtolBase(int base) {
534  return (base == 0) || (2 <= base && base <= 36);
535}
536
537static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
538  CHECK(endptr != 0);
539  if (nptr == *endptr) {
540    // No digits were found at strtol call, we need to find out the last
541    // symbol accessed by strtoll on our own.
542    // We get this symbol by skipping leading blanks and optional +/- sign.
543    while (IsSpace(*nptr)) nptr++;
544    if (*nptr == '+' || *nptr == '-') nptr++;
545    *endptr = (char*)nptr;
546  }
547  CHECK(*endptr >= nptr);
548}
549
550INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
551            char **endptr, int base) {
552  ENSURE_ASAN_INITED();
553  if (!flags()->replace_str) {
554    return REAL(strtol)(nptr, endptr, base);
555  }
556  char *real_endptr;
557  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
558  if (endptr != 0) {
559    *endptr = real_endptr;
560  }
561  if (IsValidStrtolBase(base)) {
562    FixRealStrtolEndptr(nptr, &real_endptr);
563    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
564  }
565  return result;
566}
567
568INTERCEPTOR(int, atoi, const char *nptr) {
569#if defined(__APPLE__)
570  if (!asan_inited) return REAL(atoi)(nptr);
571#endif
572  ENSURE_ASAN_INITED();
573  if (!flags()->replace_str) {
574    return REAL(atoi)(nptr);
575  }
576  char *real_endptr;
577  // "man atoi" tells that behavior of atoi(nptr) is the same as
578  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
579  // parsed integer can't be stored in *long* type (even if it's
580  // different from int). So, we just imitate this behavior.
581  int result = REAL(strtol)(nptr, &real_endptr, 10);
582  FixRealStrtolEndptr(nptr, &real_endptr);
583  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
584  return result;
585}
586
587INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
588#if defined(__APPLE__)
589  if (!asan_inited) return REAL(atol)(nptr);
590#endif
591  ENSURE_ASAN_INITED();
592  if (!flags()->replace_str) {
593    return REAL(atol)(nptr);
594  }
595  char *real_endptr;
596  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
597  FixRealStrtolEndptr(nptr, &real_endptr);
598  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
599  return result;
600}
601
602#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
603INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
604            char **endptr, int base) {
605  ENSURE_ASAN_INITED();
606  if (!flags()->replace_str) {
607    return REAL(strtoll)(nptr, endptr, base);
608  }
609  char *real_endptr;
610  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
611  if (endptr != 0) {
612    *endptr = real_endptr;
613  }
614  // If base has unsupported value, strtoll can exit with EINVAL
615  // without reading any characters. So do additional checks only
616  // if base is valid.
617  if (IsValidStrtolBase(base)) {
618    FixRealStrtolEndptr(nptr, &real_endptr);
619    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
620  }
621  return result;
622}
623
624INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
625  ENSURE_ASAN_INITED();
626  if (!flags()->replace_str) {
627    return REAL(atoll)(nptr);
628  }
629  char *real_endptr;
630  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
631  FixRealStrtolEndptr(nptr, &real_endptr);
632  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
633  return result;
634}
635#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
636
637#define ASAN_INTERCEPT_FUNC(name) do { \
638      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
639        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
640    } while (0)
641
642#if defined(_WIN32)
643INTERCEPTOR_WINAPI(DWORD, CreateThread,
644                   void* security, uptr stack_size,
645                   DWORD (__stdcall *start_routine)(void*), void* arg,
646                   DWORD flags, void* tid) {
647  GET_STACK_TRACE_THREAD;
648  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
649  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
650  asanThreadRegistry().RegisterThread(t);
651  return REAL(CreateThread)(security, stack_size,
652                            asan_thread_start, t, flags, tid);
653}
654
655namespace __asan {
656void InitializeWindowsInterceptors() {
657  ASAN_INTERCEPT_FUNC(CreateThread);
658}
659
660}  // namespace __asan
661#endif
662
663// ---------------------- InitializeAsanInterceptors ---------------- {{{1
664namespace __asan {
665void InitializeAsanInterceptors() {
666  static bool was_called_once;
667  CHECK(was_called_once == false);
668  was_called_once = true;
669#if defined(__APPLE__)
670  return;
671#else
672  SANITIZER_COMMON_INTERCEPTORS_INIT;
673
674  // Intercept mem* functions.
675  ASAN_INTERCEPT_FUNC(memcmp);
676  ASAN_INTERCEPT_FUNC(memmove);
677  ASAN_INTERCEPT_FUNC(memset);
678  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
679    ASAN_INTERCEPT_FUNC(memcpy);
680  }
681
682  // Intercept str* functions.
683  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
684  ASAN_INTERCEPT_FUNC(strchr);
685  ASAN_INTERCEPT_FUNC(strcmp);
686  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
687  ASAN_INTERCEPT_FUNC(strlen);
688  ASAN_INTERCEPT_FUNC(strncat);
689  ASAN_INTERCEPT_FUNC(strncmp);
690  ASAN_INTERCEPT_FUNC(strncpy);
691#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
692  ASAN_INTERCEPT_FUNC(strcasecmp);
693  ASAN_INTERCEPT_FUNC(strncasecmp);
694#endif
695#if ASAN_INTERCEPT_STRDUP
696  ASAN_INTERCEPT_FUNC(strdup);
697#endif
698#if ASAN_INTERCEPT_STRNLEN
699  ASAN_INTERCEPT_FUNC(strnlen);
700#endif
701#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
702  ASAN_INTERCEPT_FUNC(index);
703#endif
704
705  ASAN_INTERCEPT_FUNC(atoi);
706  ASAN_INTERCEPT_FUNC(atol);
707  ASAN_INTERCEPT_FUNC(strtol);
708#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
709  ASAN_INTERCEPT_FUNC(atoll);
710  ASAN_INTERCEPT_FUNC(strtoll);
711#endif
712
713#if ASAN_INTERCEPT_MLOCKX
714  // Intercept mlock/munlock.
715  ASAN_INTERCEPT_FUNC(mlock);
716  ASAN_INTERCEPT_FUNC(munlock);
717  ASAN_INTERCEPT_FUNC(mlockall);
718  ASAN_INTERCEPT_FUNC(munlockall);
719#endif
720
721  // Intecept signal- and jump-related functions.
722  ASAN_INTERCEPT_FUNC(longjmp);
723#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
724  ASAN_INTERCEPT_FUNC(sigaction);
725  ASAN_INTERCEPT_FUNC(signal);
726#endif
727#if ASAN_INTERCEPT_SWAPCONTEXT
728  ASAN_INTERCEPT_FUNC(swapcontext);
729#endif
730#if ASAN_INTERCEPT__LONGJMP
731  ASAN_INTERCEPT_FUNC(_longjmp);
732#endif
733#if ASAN_INTERCEPT_SIGLONGJMP
734  ASAN_INTERCEPT_FUNC(siglongjmp);
735#endif
736
737  // Intercept exception handling functions.
738#if ASAN_INTERCEPT___CXA_THROW
739  INTERCEPT_FUNCTION(__cxa_throw);
740#endif
741
742  // Intercept threading-related functions
743#if ASAN_INTERCEPT_PTHREAD_CREATE
744  ASAN_INTERCEPT_FUNC(pthread_create);
745#endif
746
747  // Some Windows-specific interceptors.
748#if defined(_WIN32)
749  InitializeWindowsInterceptors();
750#endif
751
752  if (flags()->verbosity > 0) {
753    Report("AddressSanitizer: libc interceptors initialized\n");
754  }
755#endif  // __APPLE__
756}
757
758}  // namespace __asan
759