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