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_internal.h"
18#include "asan_mapping.h"
19#include "asan_poisoning.h"
20#include "asan_report.h"
21#include "asan_stack.h"
22#include "asan_stats.h"
23#include "sanitizer_common/sanitizer_libc.h"
24
25namespace __asan {
26
27// Return true if we can quickly decide that the region is unpoisoned.
28static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
29  if (size == 0) return true;
30  if (size <= 32)
31    return !AddressIsPoisoned(beg) &&
32           !AddressIsPoisoned(beg + size - 1) &&
33           !AddressIsPoisoned(beg + size / 2);
34  return false;
35}
36
37// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
38// and ASAN_WRITE_RANGE as macro instead of function so
39// that no extra frames are created, and stack trace contains
40// relevant information only.
41// We check all shadow bytes.
42#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
43    uptr __offset = (uptr)(offset);                                     \
44    uptr __size = (uptr)(size);                                         \
45    uptr __bad = 0;                                                     \
46    if (__offset > __offset + __size) {                                 \
47      GET_STACK_TRACE_FATAL_HERE;                                       \
48      ReportStringFunctionSizeOverflow(__offset, __size, &stack);       \
49    }                                                                   \
50    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
51        (__bad = __asan_region_is_poisoned(__offset, __size))) {        \
52      GET_CURRENT_PC_BP_SP;                                             \
53      __asan_report_error(pc, bp, sp, __bad, isWrite, __size);          \
54    }                                                                   \
55  } while (0)
56
57#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
58#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
59
60// Behavior of functions like "memcpy" or "strcpy" is undefined
61// if memory intervals overlap. We report error in this case.
62// Macro is used to avoid creation of new frames.
63static inline bool RangesOverlap(const char *offset1, uptr length1,
64                                 const char *offset2, uptr length2) {
65  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
66}
67#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
68  const char *offset1 = (const char*)_offset1; \
69  const char *offset2 = (const char*)_offset2; \
70  if (RangesOverlap(offset1, length1, offset2, length2)) { \
71    GET_STACK_TRACE_FATAL_HERE; \
72    ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
73                                            offset2, length2, &stack); \
74  } \
75} while (0)
76
77static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
78#if ASAN_INTERCEPT_STRNLEN
79  if (REAL(strnlen) != 0) {
80    return REAL(strnlen)(s, maxlen);
81  }
82#endif
83  return internal_strnlen(s, maxlen);
84}
85
86void SetThreadName(const char *name) {
87  AsanThread *t = GetCurrentThread();
88  if (t)
89    asanThreadRegistry().SetThreadName(t->tid(), name);
90}
91
92int OnExit() {
93  // FIXME: ask frontend whether we need to return failure.
94  return 0;
95}
96
97}  // namespace __asan
98
99// ---------------------- Wrappers ---------------- {{{1
100using namespace __asan;  // NOLINT
101
102DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
103DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
104
105#if !SANITIZER_MAC
106#define ASAN_INTERCEPT_FUNC(name)                                        \
107  do {                                                                   \
108    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \
109      VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
110  } while (0)
111#else
112// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
113#define ASAN_INTERCEPT_FUNC(name)
114#endif  // SANITIZER_MAC
115
116#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
117#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
118  ASAN_WRITE_RANGE(ptr, size)
119#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
120#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
121  do {                                                                         \
122    if (asan_init_is_running)                                                  \
123      return REAL(func)(__VA_ARGS__);                                          \
124    ctx = 0;                                                                   \
125    (void) ctx;                                                                \
126    if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
127      return REAL(func)(__VA_ARGS__);                                          \
128    ENSURE_ASAN_INITED();                                                      \
129  } while (false)
130#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
131  do {                                         \
132  } while (false)
133#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
134  do {                                         \
135  } while (false)
136#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
137  do {                                                      \
138  } while (false)
139#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
140// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
141// But asan does not remember UserId's for threads (pthread_t);
142// and remembers all ever existed threads, so the linear search by UserId
143// can be slow.
144#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
145  do {                                                         \
146  } while (false)
147#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
148#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
149#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
150#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
151#include "sanitizer_common/sanitizer_common_interceptors.inc"
152
153#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
154#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
155#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
156  do {                                       \
157    (void)(p);                               \
158    (void)(s);                               \
159  } while (false)
160#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
161  do {                                        \
162    (void)(p);                                \
163    (void)(s);                                \
164  } while (false)
165#include "sanitizer_common/sanitizer_common_syscalls.inc"
166
167static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
168  AsanThread *t = (AsanThread*)arg;
169  SetCurrentThread(t);
170  return t->ThreadStart(GetTid());
171}
172
173#if ASAN_INTERCEPT_PTHREAD_CREATE
174INTERCEPTOR(int, pthread_create, void *thread,
175    void *attr, void *(*start_routine)(void*), void *arg) {
176  EnsureMainThreadIDIsCorrect();
177  // Strict init-order checking in thread-hostile.
178  if (flags()->strict_init_order)
179    StopInitOrderChecking();
180  GET_STACK_TRACE_THREAD;
181  int detached = 0;
182  if (attr != 0)
183    REAL(pthread_attr_getdetachstate)(attr, &detached);
184
185  u32 current_tid = GetCurrentTidOrInvalid();
186  AsanThread *t = AsanThread::Create(start_routine, arg);
187  CreateThreadContextArgs args = { t, &stack };
188  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
189  return REAL(pthread_create)(thread, attr, asan_thread_start, t);
190}
191#endif  // ASAN_INTERCEPT_PTHREAD_CREATE
192
193#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
194
195#if SANITIZER_ANDROID
196INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
197  if (!AsanInterceptsSignal(signum) ||
198      common_flags()->allow_user_segv_handler) {
199    return REAL(bsd_signal)(signum, handler);
200  }
201  return 0;
202}
203#else
204INTERCEPTOR(void*, signal, int signum, void *handler) {
205  if (!AsanInterceptsSignal(signum) ||
206      common_flags()->allow_user_segv_handler) {
207    return REAL(signal)(signum, handler);
208  }
209  return 0;
210}
211#endif
212
213INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
214                            struct sigaction *oldact) {
215  if (!AsanInterceptsSignal(signum) ||
216      common_flags()->allow_user_segv_handler) {
217    return REAL(sigaction)(signum, act, oldact);
218  }
219  return 0;
220}
221
222namespace __sanitizer {
223int real_sigaction(int signum, const void *act, void *oldact) {
224  return REAL(sigaction)(signum,
225                         (struct sigaction *)act, (struct sigaction *)oldact);
226}
227}  // namespace __sanitizer
228
229#elif SANITIZER_POSIX
230// We need to have defined REAL(sigaction) on posix systems.
231DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
232    struct sigaction *oldact)
233#endif  // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
234
235#if ASAN_INTERCEPT_SWAPCONTEXT
236static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
237  // Align to page size.
238  uptr PageSize = GetPageSizeCached();
239  uptr bottom = stack & ~(PageSize - 1);
240  ssize += stack - bottom;
241  ssize = RoundUpTo(ssize, PageSize);
242  static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
243  if (ssize && ssize <= kMaxSaneContextStackSize) {
244    PoisonShadow(bottom, ssize, 0);
245  }
246}
247
248INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
249            struct ucontext_t *ucp) {
250  static bool reported_warning = false;
251  if (!reported_warning) {
252    Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
253           "functions and may produce false positives in some cases!\n");
254    reported_warning = true;
255  }
256  // Clear shadow memory for new context (it may share stack
257  // with current context).
258  uptr stack, ssize;
259  ReadContextStack(ucp, &stack, &ssize);
260  ClearShadowMemoryForContextStack(stack, ssize);
261  int res = REAL(swapcontext)(oucp, ucp);
262  // swapcontext technically does not return, but program may swap context to
263  // "oucp" later, that would look as if swapcontext() returned 0.
264  // We need to clear shadow for ucp once again, as it may be in arbitrary
265  // state.
266  ClearShadowMemoryForContextStack(stack, ssize);
267  return res;
268}
269#endif  // ASAN_INTERCEPT_SWAPCONTEXT
270
271INTERCEPTOR(void, longjmp, void *env, int val) {
272  __asan_handle_no_return();
273  REAL(longjmp)(env, val);
274}
275
276#if ASAN_INTERCEPT__LONGJMP
277INTERCEPTOR(void, _longjmp, void *env, int val) {
278  __asan_handle_no_return();
279  REAL(_longjmp)(env, val);
280}
281#endif
282
283#if ASAN_INTERCEPT_SIGLONGJMP
284INTERCEPTOR(void, siglongjmp, void *env, int val) {
285  __asan_handle_no_return();
286  REAL(siglongjmp)(env, val);
287}
288#endif
289
290#if ASAN_INTERCEPT___CXA_THROW
291INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
292  CHECK(REAL(__cxa_throw));
293  __asan_handle_no_return();
294  REAL(__cxa_throw)(a, b, c);
295}
296#endif
297
298#if ASAN_INTERCEPT_MLOCKX
299// intercept mlock and friends.
300// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
301// All functions return 0 (success).
302static void MlockIsUnsupported() {
303  static bool printed = false;
304  if (printed) return;
305  printed = true;
306  VPrintf(1,
307          "INFO: AddressSanitizer ignores "
308          "mlock/mlockall/munlock/munlockall\n");
309}
310
311INTERCEPTOR(int, mlock, const void *addr, uptr len) {
312  MlockIsUnsupported();
313  return 0;
314}
315
316INTERCEPTOR(int, munlock, const void *addr, uptr len) {
317  MlockIsUnsupported();
318  return 0;
319}
320
321INTERCEPTOR(int, mlockall, int flags) {
322  MlockIsUnsupported();
323  return 0;
324}
325
326INTERCEPTOR(int, munlockall, void) {
327  MlockIsUnsupported();
328  return 0;
329}
330#endif
331
332static inline int CharCmp(unsigned char c1, unsigned char c2) {
333  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
334}
335
336INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
337  if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
338  ENSURE_ASAN_INITED();
339  if (flags()->replace_intrin) {
340    if (flags()->strict_memcmp) {
341      // Check the entire regions even if the first bytes of the buffers are
342      // different.
343      ASAN_READ_RANGE(a1, size);
344      ASAN_READ_RANGE(a2, size);
345      // Fallthrough to REAL(memcmp) below.
346    } else {
347      unsigned char c1 = 0, c2 = 0;
348      const unsigned char *s1 = (const unsigned char*)a1;
349      const unsigned char *s2 = (const unsigned char*)a2;
350      uptr i;
351      for (i = 0; i < size; i++) {
352        c1 = s1[i];
353        c2 = s2[i];
354        if (c1 != c2) break;
355      }
356      ASAN_READ_RANGE(s1, Min(i + 1, size));
357      ASAN_READ_RANGE(s2, Min(i + 1, size));
358      return CharCmp(c1, c2);
359    }
360  }
361  return REAL(memcmp(a1, a2, size));
362}
363
364void *__asan_memcpy(void *to, const void *from, uptr size) {
365  if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);
366  // memcpy is called during __asan_init() from the internals
367  // of printf(...).
368  if (asan_init_is_running) {
369    return REAL(memcpy)(to, from, size);
370  }
371  ENSURE_ASAN_INITED();
372  if (flags()->replace_intrin) {
373    if (to != from) {
374      // We do not treat memcpy with to==from as a bug.
375      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
376      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
377    }
378    ASAN_READ_RANGE(from, size);
379    ASAN_WRITE_RANGE(to, size);
380  }
381  return REAL(memcpy)(to, from, size);
382}
383
384void *__asan_memset(void *block, int c, uptr size) {
385  if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);
386  // memset is called inside Printf.
387  if (asan_init_is_running) {
388    return REAL(memset)(block, c, size);
389  }
390  ENSURE_ASAN_INITED();
391  if (flags()->replace_intrin) {
392    ASAN_WRITE_RANGE(block, size);
393  }
394  return REAL(memset)(block, c, size);
395}
396
397void *__asan_memmove(void *to, const void *from, uptr size) {
398  if (UNLIKELY(!asan_inited))
399    return internal_memmove(to, from, size);
400  ENSURE_ASAN_INITED();
401  if (flags()->replace_intrin) {
402    ASAN_READ_RANGE(from, size);
403    ASAN_WRITE_RANGE(to, size);
404  }
405  return internal_memmove(to, from, size);
406}
407
408INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
409  return __asan_memmove(to, from, size);
410}
411
412INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
413#if !SANITIZER_MAC
414  return __asan_memcpy(to, from, size);
415#else
416  // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
417  // with WRAP(memcpy). As a result, false positives are reported for memmove()
418  // calls. If we just disable error reporting with
419  // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
420  // internal_memcpy(), which may lead to crashes, see
421  // http://llvm.org/bugs/show_bug.cgi?id=16362.
422  return __asan_memmove(to, from, size);
423#endif  // !SANITIZER_MAC
424}
425
426INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
427  return __asan_memset(block, c, size);
428}
429
430INTERCEPTOR(char*, strchr, const char *str, int c) {
431  if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
432  // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
433  // used.
434  if (asan_init_is_running) {
435    return REAL(strchr)(str, c);
436  }
437  ENSURE_ASAN_INITED();
438  char *result = REAL(strchr)(str, c);
439  if (flags()->replace_str) {
440    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
441    ASAN_READ_RANGE(str, bytes_read);
442  }
443  return result;
444}
445
446#if ASAN_INTERCEPT_INDEX
447# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
448INTERCEPTOR(char*, index, const char *string, int c)
449  ALIAS(WRAPPER_NAME(strchr));
450# else
451#  if SANITIZER_MAC
452DECLARE_REAL(char*, index, const char *string, int c)
453OVERRIDE_FUNCTION(index, strchr);
454#  else
455DEFINE_REAL(char*, index, const char *string, int c)
456#  endif
457# endif
458#endif  // ASAN_INTERCEPT_INDEX
459
460// For both strcat() and strncat() we need to check the validity of |to|
461// argument irrespective of the |from| length.
462INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
463  ENSURE_ASAN_INITED();
464  if (flags()->replace_str) {
465    uptr from_length = REAL(strlen)(from);
466    ASAN_READ_RANGE(from, from_length + 1);
467    uptr to_length = REAL(strlen)(to);
468    ASAN_READ_RANGE(to, to_length);
469    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
470    // If the copying actually happens, the |from| string should not overlap
471    // with the resulting string starting at |to|, which has a length of
472    // to_length + from_length + 1.
473    if (from_length > 0) {
474      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
475                           from, from_length + 1);
476    }
477  }
478  return REAL(strcat)(to, from);  // NOLINT
479}
480
481INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
482  ENSURE_ASAN_INITED();
483  if (flags()->replace_str) {
484    uptr from_length = MaybeRealStrnlen(from, size);
485    uptr copy_length = Min(size, from_length + 1);
486    ASAN_READ_RANGE(from, copy_length);
487    uptr to_length = REAL(strlen)(to);
488    ASAN_READ_RANGE(to, to_length);
489    ASAN_WRITE_RANGE(to + to_length, from_length + 1);
490    if (from_length > 0) {
491      CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
492                           from, copy_length);
493    }
494  }
495  return REAL(strncat)(to, from, size);
496}
497
498INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
499#if SANITIZER_MAC
500  if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
501#endif
502  // strcpy is called from malloc_default_purgeable_zone()
503  // in __asan::ReplaceSystemAlloc() on Mac.
504  if (asan_init_is_running) {
505    return REAL(strcpy)(to, from);  // NOLINT
506  }
507  ENSURE_ASAN_INITED();
508  if (flags()->replace_str) {
509    uptr from_size = REAL(strlen)(from) + 1;
510    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
511    ASAN_READ_RANGE(from, from_size);
512    ASAN_WRITE_RANGE(to, from_size);
513  }
514  return REAL(strcpy)(to, from);  // NOLINT
515}
516
517#if ASAN_INTERCEPT_STRDUP
518INTERCEPTOR(char*, strdup, const char *s) {
519  if (UNLIKELY(!asan_inited)) return internal_strdup(s);
520  ENSURE_ASAN_INITED();
521  uptr length = REAL(strlen)(s);
522  if (flags()->replace_str) {
523    ASAN_READ_RANGE(s, length + 1);
524  }
525  GET_STACK_TRACE_MALLOC;
526  void *new_mem = asan_malloc(length + 1, &stack);
527  REAL(memcpy)(new_mem, s, length + 1);
528  return reinterpret_cast<char*>(new_mem);
529}
530#endif
531
532INTERCEPTOR(uptr, strlen, const char *s) {
533  if (UNLIKELY(!asan_inited)) return internal_strlen(s);
534  // strlen is called from malloc_default_purgeable_zone()
535  // in __asan::ReplaceSystemAlloc() on Mac.
536  if (asan_init_is_running) {
537    return REAL(strlen)(s);
538  }
539  ENSURE_ASAN_INITED();
540  uptr length = REAL(strlen)(s);
541  if (flags()->replace_str) {
542    ASAN_READ_RANGE(s, length + 1);
543  }
544  return length;
545}
546
547INTERCEPTOR(uptr, wcslen, const wchar_t *s) {
548  uptr length = REAL(wcslen)(s);
549  if (!asan_init_is_running) {
550    ENSURE_ASAN_INITED();
551    ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
552  }
553  return length;
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);
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#if SANITIZER_MAC
615  if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
616#endif
617  ENSURE_ASAN_INITED();
618  if (!flags()->replace_str) {
619    return REAL(atoi)(nptr);
620  }
621  char *real_endptr;
622  // "man atoi" tells that behavior of atoi(nptr) is the same as
623  // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
624  // parsed integer can't be stored in *long* type (even if it's
625  // different from int). So, we just imitate this behavior.
626  int result = REAL(strtol)(nptr, &real_endptr, 10);
627  FixRealStrtolEndptr(nptr, &real_endptr);
628  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
629  return result;
630}
631
632INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
633#if SANITIZER_MAC
634  if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
635#endif
636  ENSURE_ASAN_INITED();
637  if (!flags()->replace_str) {
638    return REAL(atol)(nptr);
639  }
640  char *real_endptr;
641  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
642  FixRealStrtolEndptr(nptr, &real_endptr);
643  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
644  return result;
645}
646
647#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
648INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
649            char **endptr, int base) {
650  ENSURE_ASAN_INITED();
651  if (!flags()->replace_str) {
652    return REAL(strtoll)(nptr, endptr, base);
653  }
654  char *real_endptr;
655  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
656  if (endptr != 0) {
657    *endptr = real_endptr;
658  }
659  // If base has unsupported value, strtoll can exit with EINVAL
660  // without reading any characters. So do additional checks only
661  // if base is valid.
662  if (IsValidStrtolBase(base)) {
663    FixRealStrtolEndptr(nptr, &real_endptr);
664    ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
665  }
666  return result;
667}
668
669INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
670  ENSURE_ASAN_INITED();
671  if (!flags()->replace_str) {
672    return REAL(atoll)(nptr);
673  }
674  char *real_endptr;
675  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
676  FixRealStrtolEndptr(nptr, &real_endptr);
677  ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
678  return result;
679}
680#endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
681
682static void AtCxaAtexit(void *unused) {
683  (void)unused;
684  StopInitOrderChecking();
685}
686
687#if ASAN_INTERCEPT___CXA_ATEXIT
688INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
689            void *dso_handle) {
690#if SANITIZER_MAC
691  if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
692#endif
693  ENSURE_ASAN_INITED();
694  int res = REAL(__cxa_atexit)(func, arg, dso_handle);
695  REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
696  return res;
697}
698#endif  // ASAN_INTERCEPT___CXA_ATEXIT
699
700#if ASAN_INTERCEPT_FORK
701INTERCEPTOR(int, fork, void) {
702  ENSURE_ASAN_INITED();
703  if (common_flags()->coverage) CovBeforeFork();
704  int pid = REAL(fork)();
705  if (common_flags()->coverage) CovAfterFork(pid);
706  return pid;
707}
708#endif  // ASAN_INTERCEPT_FORK
709
710#if SANITIZER_WINDOWS
711INTERCEPTOR_WINAPI(DWORD, CreateThread,
712                   void* security, uptr stack_size,
713                   DWORD (__stdcall *start_routine)(void*), void* arg,
714                   DWORD thr_flags, void* tid) {
715  // Strict init-order checking in thread-hostile.
716  if (flags()->strict_init_order)
717    StopInitOrderChecking();
718  GET_STACK_TRACE_THREAD;
719  u32 current_tid = GetCurrentTidOrInvalid();
720  AsanThread *t = AsanThread::Create(start_routine, arg);
721  CreateThreadContextArgs args = { t, &stack };
722  bool detached = false;  // FIXME: how can we determine it on Windows?
723  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
724  return REAL(CreateThread)(security, stack_size,
725                            asan_thread_start, t, thr_flags, tid);
726}
727
728namespace __asan {
729void InitializeWindowsInterceptors() {
730  ASAN_INTERCEPT_FUNC(CreateThread);
731}
732
733}  // namespace __asan
734#endif
735
736// ---------------------- InitializeAsanInterceptors ---------------- {{{1
737namespace __asan {
738void InitializeAsanInterceptors() {
739  static bool was_called_once;
740  CHECK(was_called_once == false);
741  was_called_once = true;
742  InitializeCommonInterceptors();
743
744  // Intercept mem* functions.
745  ASAN_INTERCEPT_FUNC(memcmp);
746  ASAN_INTERCEPT_FUNC(memmove);
747  ASAN_INTERCEPT_FUNC(memset);
748  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
749    ASAN_INTERCEPT_FUNC(memcpy);
750  }
751
752  // Intercept str* functions.
753  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
754  ASAN_INTERCEPT_FUNC(strchr);
755  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
756  ASAN_INTERCEPT_FUNC(strlen);
757  ASAN_INTERCEPT_FUNC(wcslen);
758  ASAN_INTERCEPT_FUNC(strncat);
759  ASAN_INTERCEPT_FUNC(strncpy);
760#if ASAN_INTERCEPT_STRDUP
761  ASAN_INTERCEPT_FUNC(strdup);
762#endif
763#if ASAN_INTERCEPT_STRNLEN
764  ASAN_INTERCEPT_FUNC(strnlen);
765#endif
766#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
767  ASAN_INTERCEPT_FUNC(index);
768#endif
769
770  ASAN_INTERCEPT_FUNC(atoi);
771  ASAN_INTERCEPT_FUNC(atol);
772  ASAN_INTERCEPT_FUNC(strtol);
773#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
774  ASAN_INTERCEPT_FUNC(atoll);
775  ASAN_INTERCEPT_FUNC(strtoll);
776#endif
777
778#if ASAN_INTERCEPT_MLOCKX
779  // Intercept mlock/munlock.
780  ASAN_INTERCEPT_FUNC(mlock);
781  ASAN_INTERCEPT_FUNC(munlock);
782  ASAN_INTERCEPT_FUNC(mlockall);
783  ASAN_INTERCEPT_FUNC(munlockall);
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#if SANITIZER_ANDROID
791  ASAN_INTERCEPT_FUNC(bsd_signal);
792#else
793  ASAN_INTERCEPT_FUNC(signal);
794#endif
795#endif
796#if ASAN_INTERCEPT_SWAPCONTEXT
797  ASAN_INTERCEPT_FUNC(swapcontext);
798#endif
799#if ASAN_INTERCEPT__LONGJMP
800  ASAN_INTERCEPT_FUNC(_longjmp);
801#endif
802#if ASAN_INTERCEPT_SIGLONGJMP
803  ASAN_INTERCEPT_FUNC(siglongjmp);
804#endif
805
806  // Intercept exception handling functions.
807#if ASAN_INTERCEPT___CXA_THROW
808  INTERCEPT_FUNCTION(__cxa_throw);
809#endif
810
811  // Intercept threading-related functions
812#if ASAN_INTERCEPT_PTHREAD_CREATE
813  ASAN_INTERCEPT_FUNC(pthread_create);
814#endif
815
816  // Intercept atexit function.
817#if ASAN_INTERCEPT___CXA_ATEXIT
818  ASAN_INTERCEPT_FUNC(__cxa_atexit);
819#endif
820
821#if ASAN_INTERCEPT_FORK
822  ASAN_INTERCEPT_FUNC(fork);
823#endif
824
825  // Some Windows-specific interceptors.
826#if SANITIZER_WINDOWS
827  InitializeWindowsInterceptors();
828#endif
829
830  VReport(1, "AddressSanitizer: libc interceptors initialized\n");
831}
832
833}  // namespace __asan
834