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