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