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