asan_interceptors.cc revision 73fe35fa6b4c437c9a723eb7bbad4863c7edbe1e
1//===-- asan_interceptors.cc ------------------------------------*- C++ -*-===//
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_interface.h"
18#include "asan_internal.h"
19#include "asan_mapping.h"
20#include "asan_stack.h"
21#include "asan_stats.h"
22#include "asan_thread_registry.h"
23#include "interception/interception.h"
24
25#include <new>
26
27#if defined(__APPLE__)
28// FIXME(samsonov): Gradually replace system headers with declarations of
29// intercepted functions.
30#include <pthread.h>
31#include <string.h>
32#include <strings.h>
33#endif  // __APPLE__
34
35#if defined(__APPLE__)
36extern "C" {
37// signal.h
38struct sigaction;
39int sigaction(int sig, const struct sigaction *act,
40              struct sigaction *oldact);
41void *signal(int signum, void *handler);
42// setjmp.h
43void longjmp(void* env, int val);
44void _longjmp(void *env, int val);
45}  // extern "C"
46#endif  // __APPLE__
47
48#if defined(_WIN32) && !defined(_DLL)
49// FIXME: We might want to use these on Mac too.
50extern "C" {
51int memcmp(const void *b1, const void *b2, size_t sz);
52void* memmove(void *d, const void *s, size_t sz);
53void* memcpy(void *d, const void *s, size_t sz);
54void* memset(void *b, int c, size_t sz);
55
56char* strchr(const char *s, char c);
57char* strcat(char *d, const char* s);  // NOLINT
58char* strncat(char *d, const char* s, size_t sz);
59char* strcpy(char *d, const char* s);  // NOLINT
60char* strncpy(char *d, const char* s, size_t sz);
61int strcmp(const char *s1, const char* s2);
62int strncmp(const char *s1, const char* s2, size_t sz);
63size_t strnlen(const char *s1, size_t sz);
64
65void longjmp(void* env, int value);
66
67__declspec(dllimport)
68void* __stdcall CreateThread(void *sec, size_t st, void* start,
69                             void *arg, DWORD fl, DWORD *id);
70}  // extern "C"
71#endif
72
73namespace __asan {
74
75// Instruments read/write access to a single byte in memory.
76// On error calls __asan_report_error, which aborts the program.
77#define ACCESS_ADDRESS(address, isWrite)   do {         \
78  if (AddressIsPoisoned(address)) {                     \
79    GET_CURRENT_PC_BP_SP;                               \
80    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
81  } \
82} while (0)
83
84// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
85// and ASAN_WRITE_RANGE as macro instead of function so
86// that no extra frames are created, and stack trace contains
87// relevant information only.
88
89// Instruments read/write access to a memory range.
90// More complex implementation is possible, for now just
91// checking the first and the last byte of a range.
92#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
93  if (size > 0) { \
94    uintptr_t ptr = (uintptr_t)(offset); \
95    ACCESS_ADDRESS(ptr, isWrite); \
96    ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
97  } \
98} while (0)
99
100#define ASAN_READ_RANGE(offset, size) do { \
101  ACCESS_MEMORY_RANGE(offset, size, false); \
102} while (0)
103
104#define ASAN_WRITE_RANGE(offset, size) do { \
105  ACCESS_MEMORY_RANGE(offset, size, true); \
106} while (0)
107
108// Behavior of functions like "memcpy" or "strcpy" is undefined
109// if memory intervals overlap. We report error in this case.
110// Macro is used to avoid creation of new frames.
111static inline bool RangesOverlap(const char *offset1, size_t length1,
112                                 const char *offset2, size_t length2) {
113  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
114}
115#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
116  const char *offset1 = (const char*)_offset1; \
117  const char *offset2 = (const char*)_offset2; \
118  if (RangesOverlap(offset1, length1, offset2, length2)) { \
119    Report("ERROR: AddressSanitizer %s-param-overlap: " \
120           "memory ranges [%p,%p) and [%p, %p) overlap\n", \
121           name, offset1, offset1 + length1, offset2, offset2 + length2); \
122    PRINT_CURRENT_STACK(); \
123    ShowStatsAndAbort(); \
124  } \
125} while (0)
126
127#define ENSURE_ASAN_INITED() do { \
128  CHECK(!asan_init_is_running); \
129  if (!asan_inited) { \
130    __asan_init(); \
131  } \
132} while (0)
133
134static inline bool IsSpace(int c) {
135  return (c == ' ') || (c == '\n') || (c == '\t') ||
136         (c == '\f') || (c == '\r') || (c == '\v');
137}
138
139static inline bool IsDigit(int c) {
140  return (c >= '0') && (c <= '9');
141}
142
143static inline int ToLower(int c) {
144  return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
145}
146
147// ---------------------- Internal string functions ---------------- {{{1
148
149int64_t internal_simple_strtoll(const char *nptr, char **endptr, int base) {
150  CHECK(base == 10);
151  while (IsSpace(*nptr)) nptr++;
152  int sgn = 1;
153  uint64_t res = 0;
154  bool have_digits = false;
155  char *old_nptr = (char*)nptr;
156  if (*nptr == '+') {
157    sgn = 1;
158    nptr++;
159  } else if (*nptr == '-') {
160    sgn = -1;
161    nptr++;
162  }
163  while (IsDigit(*nptr)) {
164    res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
165    int digit = ((*nptr) - '0');
166    res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
167    have_digits = true;
168    nptr++;
169  }
170  if (endptr != NULL) {
171    *endptr = (have_digits) ? (char*)nptr : old_nptr;
172  }
173  if (sgn > 0) {
174    return (int64_t)(Min((uint64_t)INT64_MAX, res));
175  } else {
176    return (res > INT64_MAX) ? INT64_MIN : ((int64_t)res * -1);
177  }
178}
179
180int64_t internal_atoll(const char *nptr) {
181  return internal_simple_strtoll(nptr, (char**)NULL, 10);
182}
183
184size_t internal_strlen(const char *s) {
185  size_t i = 0;
186  while (s[i]) i++;
187  return i;
188}
189
190size_t internal_strnlen(const char *s, size_t maxlen) {
191#ifndef __APPLE__
192  if (REAL(strnlen) != NULL) {
193    return REAL(strnlen)(s, maxlen);
194  }
195#endif
196  size_t i = 0;
197  while (i < maxlen && s[i]) i++;
198  return i;
199}
200
201char* internal_strchr(const char *s, int c) {
202  while (true) {
203    if (*s == (char)c)
204      return (char*)s;
205    if (*s == 0)
206      return NULL;
207    s++;
208  }
209}
210
211void* internal_memchr(const void* s, int c, size_t n) {
212  const char* t = (char*)s;
213  for (size_t i = 0; i < n; ++i, ++t)
214    if (*t == c)
215      return (void*)t;
216  return NULL;
217}
218
219int internal_memcmp(const void* s1, const void* s2, size_t n) {
220  const char* t1 = (char*)s1;
221  const char* t2 = (char*)s2;
222  for (size_t i = 0; i < n; ++i, ++t1, ++t2)
223    if (*t1 != *t2)
224      return *t1 < *t2 ? -1 : 1;
225  return 0;
226}
227
228char *internal_strstr(const char *haystack, const char *needle) {
229  // This is O(N^2), but we are not using it in hot places.
230  size_t len1 = internal_strlen(haystack);
231  size_t len2 = internal_strlen(needle);
232  if (len1 < len2) return 0;
233  for (size_t pos = 0; pos <= len1 - len2; pos++) {
234    if (internal_memcmp(haystack + pos, needle, len2) == 0)
235      return (char*)haystack + pos;
236  }
237  return 0;
238}
239
240char *internal_strncat(char *dst, const char *src, size_t n) {
241  size_t len = internal_strlen(dst);
242  size_t i;
243  for (i = 0; i < n && src[i]; i++)
244    dst[len + i] = src[i];
245  dst[len + i] = 0;
246  return dst;
247}
248
249int internal_strcmp(const char *s1, const char *s2) {
250  while (true) {
251    unsigned c1 = *s1;
252    unsigned c2 = *s2;
253    if (c1 != c2) return (c1 < c2) ? -1 : 1;
254    if (c1 == 0) break;
255    s1++;
256    s2++;
257  }
258  return 0;
259}
260
261char *internal_strncpy(char *dst, const char *src, size_t n) {
262  size_t i;
263  for (i = 0; i < n && src[i]; i++)
264    dst[i] = src[i];
265  return dst;
266}
267
268}  // namespace __asan
269
270// ---------------------- Wrappers ---------------- {{{1
271using namespace __asan;  // NOLINT
272
273#define OPERATOR_NEW_BODY \
274  GET_STACK_TRACE_HERE_FOR_MALLOC;\
275  return asan_memalign(0, size, &stack);
276
277#ifdef ANDROID
278void *operator new(size_t size) { OPERATOR_NEW_BODY; }
279void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
280#else
281void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
282void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
283void *operator new(size_t size, std::nothrow_t const&) throw()
284{ OPERATOR_NEW_BODY; }
285void *operator new[](size_t size, std::nothrow_t const&) throw()
286{ OPERATOR_NEW_BODY; }
287#endif
288
289#define OPERATOR_DELETE_BODY \
290  GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
291  asan_free(ptr, &stack);
292
293void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
294void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
295void operator delete(void *ptr, std::nothrow_t const&) throw()
296{ OPERATOR_DELETE_BODY; }
297void operator delete[](void *ptr, std::nothrow_t const&) throw()
298{ OPERATOR_DELETE_BODY;}
299
300static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
301  AsanThread *t = (AsanThread*)arg;
302  asanThreadRegistry().SetCurrent(t);
303  return t->ThreadStart();
304}
305
306#ifndef _WIN32
307INTERCEPTOR(int, pthread_create, void *thread,
308    void *attr, void *(*start_routine)(void*), void *arg) {
309  GET_STACK_TRACE_HERE(kStackTraceMax);
310  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
311  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
312  asanThreadRegistry().RegisterThread(t);
313  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
314}
315#endif  // !_WIN32
316
317#if !defined(ANDROID) && !defined(_WIN32)
318INTERCEPTOR(void*, signal, int signum, void *handler) {
319  if (!AsanInterceptsSignal(signum)) {
320    return REAL(signal)(signum, handler);
321  }
322  return NULL;
323}
324
325INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
326                            struct sigaction *oldact) {
327  if (!AsanInterceptsSignal(signum)) {
328    return REAL(sigaction)(signum, act, oldact);
329  }
330  return 0;
331}
332#endif  // !ANDROID && !_WIN32
333
334INTERCEPTOR(void, longjmp, void *env, int val) {
335  __asan_handle_no_return();
336  REAL(longjmp)(env, val);
337}
338
339#if !defined(_WIN32)
340INTERCEPTOR(void, _longjmp, void *env, int val) {
341  __asan_handle_no_return();
342  REAL(_longjmp)(env, val);
343}
344
345INTERCEPTOR(void, siglongjmp, void *env, int val) {
346  __asan_handle_no_return();
347  REAL(siglongjmp)(env, val);
348}
349#endif
350
351#if ASAN_HAS_EXCEPTIONS == 1
352#ifdef __APPLE__
353extern "C" void __cxa_throw(void *a, void *b, void *c);
354#endif  // __APPLE__
355
356INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
357  CHECK(REAL(__cxa_throw));
358  __asan_handle_no_return();
359  REAL(__cxa_throw)(a, b, c);
360}
361#endif
362
363// intercept mlock and friends.
364// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
365// All functions return 0 (success).
366static void MlockIsUnsupported() {
367  static bool printed = 0;
368  if (printed) return;
369  printed = true;
370  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
371}
372
373extern "C" {
374INTERCEPTOR_ATTRIBUTE
375int mlock(const void *addr, size_t len) {
376  MlockIsUnsupported();
377  return 0;
378}
379
380INTERCEPTOR_ATTRIBUTE
381int munlock(const void *addr, size_t len) {
382  MlockIsUnsupported();
383  return 0;
384}
385
386INTERCEPTOR_ATTRIBUTE
387int mlockall(int flags) {
388  MlockIsUnsupported();
389  return 0;
390}
391
392INTERCEPTOR_ATTRIBUTE
393int munlockall(void) {
394  MlockIsUnsupported();
395  return 0;
396}
397}  // extern "C"
398
399static inline int CharCmp(unsigned char c1, unsigned char c2) {
400  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
401}
402
403static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
404  int c1_low = ToLower(c1);
405  int c2_low = ToLower(c2);
406  return c1_low - c2_low;
407}
408
409INTERCEPTOR(int, memcmp, const void *a1, const void *a2, size_t size) {
410  ENSURE_ASAN_INITED();
411  unsigned char c1 = 0, c2 = 0;
412  const unsigned char *s1 = (const unsigned char*)a1;
413  const unsigned char *s2 = (const unsigned char*)a2;
414  size_t i;
415  for (i = 0; i < size; i++) {
416    c1 = s1[i];
417    c2 = s2[i];
418    if (c1 != c2) break;
419  }
420  ASAN_READ_RANGE(s1, Min(i + 1, size));
421  ASAN_READ_RANGE(s2, Min(i + 1, size));
422  return CharCmp(c1, c2);
423}
424
425INTERCEPTOR(void*, memcpy, void *to, const void *from, size_t size) {
426  // memcpy is called during __asan_init() from the internals
427  // of printf(...).
428  if (asan_init_is_running) {
429    return REAL(memcpy)(to, from, size);
430  }
431  ENSURE_ASAN_INITED();
432  if (FLAG_replace_intrin) {
433    if (to != from) {
434      // We do not treat memcpy with to==from as a bug.
435      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
436      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
437    }
438    ASAN_WRITE_RANGE(from, size);
439    ASAN_READ_RANGE(to, size);
440  }
441  return REAL(memcpy)(to, from, size);
442}
443
444INTERCEPTOR(void*, memmove, void *to, const void *from, size_t size) {
445  ENSURE_ASAN_INITED();
446  if (FLAG_replace_intrin) {
447    ASAN_WRITE_RANGE(from, size);
448    ASAN_READ_RANGE(to, size);
449  }
450  return REAL(memmove)(to, from, size);
451}
452
453INTERCEPTOR(void*, memset, void *block, int c, size_t size) {
454  // memset is called inside INTERCEPT_FUNCTION on Mac.
455  if (asan_init_is_running) {
456    return REAL(memset)(block, c, size);
457  }
458  ENSURE_ASAN_INITED();
459  if (FLAG_replace_intrin) {
460    ASAN_WRITE_RANGE(block, size);
461  }
462  return REAL(memset)(block, c, size);
463}
464
465INTERCEPTOR(char*, strchr, const char *str, int c) {
466  ENSURE_ASAN_INITED();
467  char *result = REAL(strchr)(str, c);
468  if (FLAG_replace_str) {
469    size_t bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
470    ASAN_READ_RANGE(str, bytes_read);
471  }
472  return result;
473}
474
475#ifdef __linux__
476INTERCEPTOR(char*, index, const char *string, int c)
477  ALIAS(WRAPPER_NAME(strchr));
478#else
479DEFINE_REAL(char*, index, const char *string, int c);
480#endif
481
482#ifdef ANDROID
483DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
484    struct sigaction *oldact);
485#endif
486
487INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
488  ENSURE_ASAN_INITED();
489  unsigned char c1, c2;
490  size_t i;
491  for (i = 0; ; i++) {
492    c1 = (unsigned char)s1[i];
493    c2 = (unsigned char)s2[i];
494    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
495  }
496  ASAN_READ_RANGE(s1, i + 1);
497  ASAN_READ_RANGE(s2, i + 1);
498  return CharCaseCmp(c1, c2);
499}
500
501INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
502  ENSURE_ASAN_INITED();
503  if (FLAG_replace_str) {
504    size_t from_length = REAL(strlen)(from);
505    ASAN_READ_RANGE(from, from_length + 1);
506    if (from_length > 0) {
507      size_t to_length = REAL(strlen)(to);
508      ASAN_READ_RANGE(to, to_length);
509      ASAN_WRITE_RANGE(to + to_length, from_length + 1);
510      CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1);
511    }
512  }
513  return REAL(strcat)(to, from);  // NOLINT
514}
515
516INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
517  if (!asan_inited) {
518    return internal_strcmp(s1, s2);
519  }
520  unsigned char c1, c2;
521  size_t i;
522  for (i = 0; ; i++) {
523    c1 = (unsigned char)s1[i];
524    c2 = (unsigned char)s2[i];
525    if (c1 != c2 || c1 == '\0') break;
526  }
527  ASAN_READ_RANGE(s1, i + 1);
528  ASAN_READ_RANGE(s2, i + 1);
529  return CharCmp(c1, c2);
530}
531
532INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
533  // strcpy is called from malloc_default_purgeable_zone()
534  // in __asan::ReplaceSystemAlloc() on Mac.
535  if (asan_init_is_running) {
536    return REAL(strcpy)(to, from);  // NOLINT
537  }
538  ENSURE_ASAN_INITED();
539  if (FLAG_replace_str) {
540    size_t from_size = REAL(strlen)(from) + 1;
541    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
542    ASAN_READ_RANGE(from, from_size);
543    ASAN_WRITE_RANGE(to, from_size);
544  }
545  return REAL(strcpy)(to, from);  // NOLINT
546}
547
548INTERCEPTOR(char*, strdup, const char *s) {
549  ENSURE_ASAN_INITED();
550  if (FLAG_replace_str) {
551    size_t length = REAL(strlen)(s);
552    ASAN_READ_RANGE(s, length + 1);
553  }
554  return REAL(strdup)(s);
555}
556
557INTERCEPTOR(size_t, strlen, const char *s) {
558  // strlen is called from malloc_default_purgeable_zone()
559  // in __asan::ReplaceSystemAlloc() on Mac.
560  if (asan_init_is_running) {
561    return REAL(strlen)(s);
562  }
563  ENSURE_ASAN_INITED();
564  size_t length = REAL(strlen)(s);
565  if (FLAG_replace_str) {
566    ASAN_READ_RANGE(s, length + 1);
567  }
568  return length;
569}
570
571INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, size_t n) {
572  ENSURE_ASAN_INITED();
573  unsigned char c1 = 0, c2 = 0;
574  size_t i;
575  for (i = 0; i < n; i++) {
576    c1 = (unsigned char)s1[i];
577    c2 = (unsigned char)s2[i];
578    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
579  }
580  ASAN_READ_RANGE(s1, Min(i + 1, n));
581  ASAN_READ_RANGE(s2, Min(i + 1, n));
582  return CharCaseCmp(c1, c2);
583}
584
585INTERCEPTOR(int, strncmp, const char *s1, const char *s2, size_t size) {
586  // strncmp is called from malloc_default_purgeable_zone()
587  // in __asan::ReplaceSystemAlloc() on Mac.
588  if (asan_init_is_running) {
589    return REAL(strncmp)(s1, s2, size);
590  }
591  unsigned char c1 = 0, c2 = 0;
592  size_t i;
593  for (i = 0; i < size; i++) {
594    c1 = (unsigned char)s1[i];
595    c2 = (unsigned char)s2[i];
596    if (c1 != c2 || c1 == '\0') break;
597  }
598  ASAN_READ_RANGE(s1, Min(i + 1, size));
599  ASAN_READ_RANGE(s2, Min(i + 1, size));
600  return CharCmp(c1, c2);
601}
602
603INTERCEPTOR(char*, strncpy, char *to, const char *from, size_t size) {
604  ENSURE_ASAN_INITED();
605  if (FLAG_replace_str) {
606    size_t from_size = Min(size, internal_strnlen(from, size) + 1);
607    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
608    ASAN_READ_RANGE(from, from_size);
609    ASAN_WRITE_RANGE(to, size);
610  }
611  return REAL(strncpy)(to, from, size);
612}
613
614#ifndef __APPLE__
615INTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
616  ENSURE_ASAN_INITED();
617  size_t length = REAL(strnlen)(s, maxlen);
618  if (FLAG_replace_str) {
619    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
620  }
621  return length;
622}
623#endif
624
625#if defined(_WIN32)
626INTERCEPTOR_WINAPI(DWORD, CreateThread,
627                   void* security, size_t stack_size,
628                   DWORD (__stdcall *start_routine)(void*), void* arg,
629                   DWORD flags, void* tid) {
630  GET_STACK_TRACE_HERE(kStackTraceMax);
631  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
632  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
633  asanThreadRegistry().RegisterThread(t);
634  return REAL(CreateThread)(security, stack_size,
635                            asan_thread_start, t, flags, tid);
636}
637
638namespace __asan {
639void InitializeWindowsInterceptors() {
640  CHECK(INTERCEPT_FUNCTION(CreateThread));
641}
642
643}  // namespace __asan
644#endif
645
646// ---------------------- InitializeAsanInterceptors ---------------- {{{1
647namespace __asan {
648void InitializeAsanInterceptors() {
649  static bool was_called_once;
650  CHECK(was_called_once == false);
651  was_called_once = true;
652  // Intercept mem* functions.
653  CHECK(INTERCEPT_FUNCTION(memcmp));
654  CHECK(INTERCEPT_FUNCTION(memmove));
655  CHECK(INTERCEPT_FUNCTION(memset));
656  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
657    CHECK(INTERCEPT_FUNCTION(memcpy));
658  } else {
659    REAL(memcpy) = REAL(memmove);
660  }
661
662  // Intercept str* functions.
663  CHECK(INTERCEPT_FUNCTION(strcat));  // NOLINT
664  CHECK(INTERCEPT_FUNCTION(strchr));
665  CHECK(INTERCEPT_FUNCTION(strcmp));
666  CHECK(INTERCEPT_FUNCTION(strcpy));  // NOLINT
667  CHECK(INTERCEPT_FUNCTION(strlen));
668  CHECK(INTERCEPT_FUNCTION(strncmp));
669  CHECK(INTERCEPT_FUNCTION(strncpy));
670#if !defined(_WIN32)
671  CHECK(INTERCEPT_FUNCTION(strcasecmp));
672  CHECK(INTERCEPT_FUNCTION(strdup));
673  CHECK(INTERCEPT_FUNCTION(strncasecmp));
674# ifndef __APPLE__
675  CHECK(INTERCEPT_FUNCTION(index));
676# else
677  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
678# endif
679#endif
680#if !defined(__APPLE__)
681  CHECK(INTERCEPT_FUNCTION(strnlen));
682#endif
683
684  // Intecept signal- and jump-related functions.
685  CHECK(INTERCEPT_FUNCTION(longjmp));
686#if !defined(ANDROID) && !defined(_WIN32)
687  CHECK(INTERCEPT_FUNCTION(sigaction));
688  CHECK(INTERCEPT_FUNCTION(signal));
689#endif
690
691#if !defined(_WIN32)
692  CHECK(INTERCEPT_FUNCTION(_longjmp));
693  INTERCEPT_FUNCTION(__cxa_throw);
694# if !defined(__APPLE__)
695  // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
696  // there.
697  CHECK(INTERCEPT_FUNCTION(siglongjmp));
698# endif
699#endif
700
701  // Intercept threading-related functions
702#if !defined(_WIN32)
703  CHECK(INTERCEPT_FUNCTION(pthread_create));
704#endif
705
706  // Some Windows-specific interceptors.
707#if defined(_WIN32)
708  InitializeWindowsInterceptors();
709#endif
710
711  // Some Mac-specific interceptors.
712#if defined(__APPLE__)
713  InitializeMacInterceptors();
714#endif
715
716  if (FLAG_v > 0) {
717    Report("AddressSanitizer: libc interceptors initialized\n");
718  }
719}
720
721}  // namespace __asan
722