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