asan_interceptors.cc revision 37b3fcd6fdec5740fe51fc1315c5d4d54313de98
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
411// For both strcat() and strncat() we need to check the validity of |to|
412// argument irrespective of the |from| length.
413INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
414  ENSURE_ASAN_INITED();
415  if (flags()->replace_str) {
416    uptr from_length = REAL(strlen)(from);
417    ASAN_READ_RANGE(from, from_length + 1);
418    uptr to_length = REAL(strlen)(to);
419    ASAN_READ_RANGE(to, to_length);
420    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
421    // If the copying actually happens, the |from| string should not overlap
422    // with the resulting string starting at |to|, which has a length of
423    // to_length + from_length + 1.
424    if (from_length > 0) {
425      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
426                           from, from_length + 1);
427    }
428  }
429  return REAL(strcat)(to, from);  // NOLINT
430}
431
432INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
433  ENSURE_ASAN_INITED();
434  if (flags()->replace_str) {
435    uptr from_length = MaybeRealStrnlen(from, size);
436    uptr copy_length = Min(size, from_length + 1);
437    ASAN_READ_RANGE(from, copy_length);
438    uptr to_length = REAL(strlen)(to);
439    ASAN_READ_RANGE(to, to_length);
440    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
441    if (from_length > 0) {
442      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
443                           from, copy_length);
444    }
445  }
446  return REAL(strncat)(to, from, size);
447}
448
449INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
450  if (asan_init_is_running) {
451    return REAL(strcmp)(s1, s2);
452  }
453  ENSURE_ASAN_INITED();
454  unsigned char c1, c2;
455  uptr i;
456  for (i = 0; ; i++) {
457    c1 = (unsigned char)s1[i];
458    c2 = (unsigned char)s2[i];
459    if (c1 != c2 || c1 == '\0') break;
460  }
461  ASAN_READ_RANGE(s1, i + 1);
462  ASAN_READ_RANGE(s2, i + 1);
463  return CharCmp(c1, c2);
464}
465
466INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
467  // strcpy is called from malloc_default_purgeable_zone()
468  // in __asan::ReplaceSystemAlloc() on Mac.
469  if (asan_init_is_running) {
470    return REAL(strcpy)(to, from);  // NOLINT
471  }
472  ENSURE_ASAN_INITED();
473  if (flags()->replace_str) {
474    uptr from_size = REAL(strlen)(from) + 1;
475    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
476    ASAN_READ_RANGE(from, from_size);
477    ASAN_WRITE_RANGE(to, from_size);
478  }
479  return REAL(strcpy)(to, from);  // NOLINT
480}
481
482#if ASAN_INTERCEPT_STRDUP
483INTERCEPTOR(char*, strdup, const char *s) {
484  ENSURE_ASAN_INITED();
485  if (flags()->replace_str) {
486    uptr length = REAL(strlen)(s);
487    ASAN_READ_RANGE(s, length + 1);
488  }
489  return REAL(strdup)(s);
490}
491#endif
492
493INTERCEPTOR(uptr, strlen, const char *s) {
494  // strlen is called from malloc_default_purgeable_zone()
495  // in __asan::ReplaceSystemAlloc() on Mac.
496  if (asan_init_is_running) {
497    return REAL(strlen)(s);
498  }
499  ENSURE_ASAN_INITED();
500  uptr length = REAL(strlen)(s);
501  if (flags()->replace_str) {
502    ASAN_READ_RANGE(s, length + 1);
503  }
504  return length;
505}
506
507#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
508INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
509  ENSURE_ASAN_INITED();
510  unsigned char c1, c2;
511  uptr i;
512  for (i = 0; ; i++) {
513    c1 = (unsigned char)s1[i];
514    c2 = (unsigned char)s2[i];
515    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
516  }
517  ASAN_READ_RANGE(s1, i + 1);
518  ASAN_READ_RANGE(s2, i + 1);
519  return CharCaseCmp(c1, c2);
520}
521
522INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
523  ENSURE_ASAN_INITED();
524  unsigned char c1 = 0, c2 = 0;
525  uptr i;
526  for (i = 0; i < n; i++) {
527    c1 = (unsigned char)s1[i];
528    c2 = (unsigned char)s2[i];
529    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
530  }
531  ASAN_READ_RANGE(s1, Min(i + 1, n));
532  ASAN_READ_RANGE(s2, Min(i + 1, n));
533  return CharCaseCmp(c1, c2);
534}
535#endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
536
537INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
538  // strncmp is called from malloc_default_purgeable_zone()
539  // in __asan::ReplaceSystemAlloc() on Mac.
540  if (asan_init_is_running) {
541    return REAL(strncmp)(s1, s2, size);
542  }
543  ENSURE_ASAN_INITED();
544  unsigned char c1 = 0, c2 = 0;
545  uptr i;
546  for (i = 0; i < size; i++) {
547    c1 = (unsigned char)s1[i];
548    c2 = (unsigned char)s2[i];
549    if (c1 != c2 || c1 == '\0') break;
550  }
551  ASAN_READ_RANGE(s1, Min(i + 1, size));
552  ASAN_READ_RANGE(s2, Min(i + 1, size));
553  return CharCmp(c1, c2);
554}
555
556INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
557  ENSURE_ASAN_INITED();
558  if (flags()->replace_str) {
559    uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
560    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
561    ASAN_READ_RANGE(from, from_size);
562    ASAN_WRITE_RANGE(to, size);
563  }
564  return REAL(strncpy)(to, from, size);
565}
566
567#if ASAN_INTERCEPT_STRNLEN
568INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
569  ENSURE_ASAN_INITED();
570  uptr length = REAL(strnlen)(s, maxlen);
571  if (flags()->replace_str) {
572    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
573  }
574  return length;
575}
576#endif  // ASAN_INTERCEPT_STRNLEN
577
578static inline bool IsValidStrtolBase(int base) {
579  return (base == 0) || (2 <= base && base <= 36);
580}
581
582static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
583  CHECK(endptr != 0);
584  if (nptr == *endptr) {
585    // No digits were found at strtol call, we need to find out the last
586    // symbol accessed by strtoll on our own.
587    // We get this symbol by skipping leading blanks and optional +/- sign.
588    while (IsSpace(*nptr)) nptr++;
589    if (*nptr == '+' || *nptr == '-') nptr++;
590    *endptr = (char*)nptr;
591  }
592  CHECK(*endptr >= nptr);
593}
594
595INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
596            char **endptr, int base) {
597  ENSURE_ASAN_INITED();
598  if (!flags()->replace_str) {
599    return REAL(strtol)(nptr, endptr, base);
600  }
601  char *real_endptr;
602  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
603  if (endptr != 0) {
604    *endptr = real_endptr;
605  }
606  if (IsValidStrtolBase(base)) {
607    FixRealStrtolEndptr(nptr, &real_endptr);
608    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
609  }
610  return result;
611}
612
613INTERCEPTOR(int, atoi, const char *nptr) {
614  ENSURE_ASAN_INITED();
615  if (!flags()->replace_str) {
616    return REAL(atoi)(nptr);
617  }
618  char *real_endptr;
619  // "man atoi" tells that behavior of atoi(nptr) is the same as
620  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
621  // parsed integer can't be stored in *long* type (even if it's
622  // different from int). So, we just imitate this behavior.
623  int result = REAL(strtol)(nptr, &real_endptr, 10);
624  FixRealStrtolEndptr(nptr, &real_endptr);
625  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
626  return result;
627}
628
629INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
630  ENSURE_ASAN_INITED();
631  if (!flags()->replace_str) {
632    return REAL(atol)(nptr);
633  }
634  char *real_endptr;
635  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
636  FixRealStrtolEndptr(nptr, &real_endptr);
637  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
638  return result;
639}
640
641#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
642INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
643            char **endptr, int base) {
644  ENSURE_ASAN_INITED();
645  if (!flags()->replace_str) {
646    return REAL(strtoll)(nptr, endptr, base);
647  }
648  char *real_endptr;
649  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
650  if (endptr != 0) {
651    *endptr = real_endptr;
652  }
653  // If base has unsupported value, strtoll can exit with EINVAL
654  // without reading any characters. So do additional checks only
655  // if base is valid.
656  if (IsValidStrtolBase(base)) {
657    FixRealStrtolEndptr(nptr, &real_endptr);
658    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
659  }
660  return result;
661}
662
663INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
664  ENSURE_ASAN_INITED();
665  if (!flags()->replace_str) {
666    return REAL(atoll)(nptr);
667  }
668  char *real_endptr;
669  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
670  FixRealStrtolEndptr(nptr, &real_endptr);
671  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
672  return result;
673}
674#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
675
676#define ASAN_INTERCEPT_FUNC(name) do { \
677      if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
678        Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
679    } while (0)
680
681#if defined(_WIN32)
682INTERCEPTOR_WINAPI(DWORD, CreateThread,
683                   void* security, uptr stack_size,
684                   DWORD (__stdcall *start_routine)(void*), void* arg,
685                   DWORD flags, void* tid) {
686  GET_STACK_TRACE_HERE(kStackTraceMax);
687  u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
688  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
689  asanThreadRegistry().RegisterThread(t);
690  return REAL(CreateThread)(security, stack_size,
691                            asan_thread_start, t, flags, tid);
692}
693
694namespace __asan {
695void InitializeWindowsInterceptors() {
696  ASAN_INTERCEPT_FUNC(CreateThread);
697}
698
699}  // namespace __asan
700#endif
701
702// ---------------------- InitializeAsanInterceptors ---------------- {{{1
703namespace __asan {
704void InitializeAsanInterceptors() {
705  static bool was_called_once;
706  CHECK(was_called_once == false);
707  was_called_once = true;
708  // Intercept mem* functions.
709  ASAN_INTERCEPT_FUNC(memcmp);
710  ASAN_INTERCEPT_FUNC(memmove);
711  ASAN_INTERCEPT_FUNC(memset);
712  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
713    ASAN_INTERCEPT_FUNC(memcpy);
714  } else {
715    REAL(memcpy) = REAL(memmove);
716  }
717
718  // Intercept str* functions.
719  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
720  ASAN_INTERCEPT_FUNC(strchr);
721  ASAN_INTERCEPT_FUNC(strcmp);
722  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
723  ASAN_INTERCEPT_FUNC(strlen);
724  ASAN_INTERCEPT_FUNC(strncat);
725  ASAN_INTERCEPT_FUNC(strncmp);
726  ASAN_INTERCEPT_FUNC(strncpy);
727#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
728  ASAN_INTERCEPT_FUNC(strcasecmp);
729  ASAN_INTERCEPT_FUNC(strncasecmp);
730#endif
731#if ASAN_INTERCEPT_STRDUP
732  ASAN_INTERCEPT_FUNC(strdup);
733#endif
734#if ASAN_INTERCEPT_STRNLEN
735  ASAN_INTERCEPT_FUNC(strnlen);
736#endif
737#if ASAN_INTERCEPT_INDEX
738# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
739  ASAN_INTERCEPT_FUNC(index);
740# else
741  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
742# endif
743#endif
744
745  ASAN_INTERCEPT_FUNC(atoi);
746  ASAN_INTERCEPT_FUNC(atol);
747  ASAN_INTERCEPT_FUNC(strtol);
748#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
749  ASAN_INTERCEPT_FUNC(atoll);
750  ASAN_INTERCEPT_FUNC(strtoll);
751#endif
752
753  // Intecept signal- and jump-related functions.
754  ASAN_INTERCEPT_FUNC(longjmp);
755#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
756  ASAN_INTERCEPT_FUNC(sigaction);
757  ASAN_INTERCEPT_FUNC(signal);
758#endif
759#if ASAN_INTERCEPT__LONGJMP
760  ASAN_INTERCEPT_FUNC(_longjmp);
761#endif
762#if ASAN_INTERCEPT_SIGLONGJMP
763  ASAN_INTERCEPT_FUNC(siglongjmp);
764#endif
765
766  // Intercept exception handling functions.
767#if ASAN_INTERCEPT___CXA_THROW
768  INTERCEPT_FUNCTION(__cxa_throw);
769#endif
770
771  // Intercept threading-related functions
772#if ASAN_INTERCEPT_PTHREAD_CREATE
773  ASAN_INTERCEPT_FUNC(pthread_create);
774#endif
775
776  // Some Windows-specific interceptors.
777#if defined(_WIN32)
778  InitializeWindowsInterceptors();
779#endif
780
781  // Some Mac-specific interceptors.
782#if defined(__APPLE__)
783  InitializeMacInterceptors();
784#endif
785
786  if (flags()->verbosity > 0) {
787    Report("AddressSanitizer: libc interceptors initialized\n");
788  }
789}
790
791}  // namespace __asan
792