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