• 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_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 
25 namespace __asan {
26 
27 // Return true if we can quickly decide that the region is unpoisoned.
QuickCheckForUnpoisonedRegion(uptr beg,uptr size)28 static 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.
RangesOverlap(const char * offset1,uptr length1,const char * offset2,uptr length2)63 static 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 
MaybeRealStrnlen(const char * s,uptr maxlen)77 static 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 
SetThreadName(const char * name)86 void SetThreadName(const char *name) {
87   AsanThread *t = GetCurrentThread();
88   if (t)
89     asanThreadRegistry().SetThreadName(t->tid(), name);
90 }
91 
OnExit()92 int OnExit() {
93   // FIXME: ask frontend whether we need to return failure.
94   return 0;
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 #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 
167 static 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
INTERCEPTOR(int,pthread_create,void * thread,void * attr,void * (* start_routine)(void *),void * arg)174 INTERCEPTOR(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
INTERCEPTOR(void *,bsd_signal,int signum,void * handler)196 INTERCEPTOR(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
INTERCEPTOR(void *,signal,int signum,void * handler)204 INTERCEPTOR(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 
INTERCEPTOR(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)213 INTERCEPTOR(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 
222 namespace __sanitizer {
real_sigaction(int signum,const void * act,void * oldact)223 int 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.
DEFINE_REAL(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)231 DEFINE_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
236 static 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 
INTERCEPTOR(int,swapcontext,struct ucontext_t * oucp,struct ucontext_t * ucp)248 INTERCEPTOR(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 
INTERCEPTOR(void,longjmp,void * env,int val)271 INTERCEPTOR(void, longjmp, void *env, int val) {
272   __asan_handle_no_return();
273   REAL(longjmp)(env, val);
274 }
275 
276 #if ASAN_INTERCEPT__LONGJMP
INTERCEPTOR(void,_longjmp,void * env,int val)277 INTERCEPTOR(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
INTERCEPTOR(void,siglongjmp,void * env,int val)284 INTERCEPTOR(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
INTERCEPTOR(void,__cxa_throw,void * a,void * b,void * c)291 INTERCEPTOR(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).
MlockIsUnsupported()302 static 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 
INTERCEPTOR(int,mlock,const void * addr,uptr len)311 INTERCEPTOR(int, mlock, const void *addr, uptr len) {
312   MlockIsUnsupported();
313   return 0;
314 }
315 
INTERCEPTOR(int,munlock,const void * addr,uptr len)316 INTERCEPTOR(int, munlock, const void *addr, uptr len) {
317   MlockIsUnsupported();
318   return 0;
319 }
320 
INTERCEPTOR(int,mlockall,int flags)321 INTERCEPTOR(int, mlockall, int flags) {
322   MlockIsUnsupported();
323   return 0;
324 }
325 
INTERCEPTOR(int,munlockall,void)326 INTERCEPTOR(int, munlockall, void) {
327   MlockIsUnsupported();
328   return 0;
329 }
330 #endif
331 
CharCmp(unsigned char c1,unsigned char c2)332 static inline int CharCmp(unsigned char c1, unsigned char c2) {
333   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
334 }
335 
INTERCEPTOR(int,memcmp,const void * a1,const void * a2,uptr size)336 INTERCEPTOR(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 
__asan_memcpy(void * to,const void * from,uptr size)364 void *__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 
__asan_memset(void * block,int c,uptr size)384 void *__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 
__asan_memmove(void * to,const void * from,uptr size)397 void *__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 
INTERCEPTOR(void *,memmove,void * to,const void * from,uptr size)408 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
409   return __asan_memmove(to, from, size);
410 }
411 
INTERCEPTOR(void *,memcpy,void * to,const void * from,uptr size)412 INTERCEPTOR(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 
INTERCEPTOR(void *,memset,void * block,int c,uptr size)426 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
427   return __asan_memset(block, c, size);
428 }
429 
INTERCEPTOR(char *,strchr,const char * str,int c)430 INTERCEPTOR(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
448 INTERCEPTOR(char*, index, const char *string, int c)
449   ALIAS(WRAPPER_NAME(strchr));
450 # else
451 #  if SANITIZER_MAC
452 DECLARE_REAL(char*, index, const char *string, int c)
453 OVERRIDE_FUNCTION(index, strchr);
454 #  else
DEFINE_REAL(char *,index,const char * string,int c)455 DEFINE_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.
462 INTERCEPTOR(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 
INTERCEPTOR(char *,strncat,char * to,const char * from,uptr size)481 INTERCEPTOR(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 
INTERCEPTOR(char *,strcpy,char * to,const char * from)498 INTERCEPTOR(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
INTERCEPTOR(char *,strdup,const char * s)518 INTERCEPTOR(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 
INTERCEPTOR(uptr,strlen,const char * s)532 INTERCEPTOR(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 
INTERCEPTOR(uptr,wcslen,const wchar_t * s)547 INTERCEPTOR(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 
INTERCEPTOR(char *,strncpy,char * to,const char * from,uptr size)556 INTERCEPTOR(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
INTERCEPTOR(uptr,strnlen,const char * s,uptr maxlen)568 INTERCEPTOR(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 
IsValidStrtolBase(int base)578 static inline bool IsValidStrtolBase(int base) {
579   return (base == 0) || (2 <= base && base <= 36);
580 }
581 
FixRealStrtolEndptr(const char * nptr,char ** endptr)582 static 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 
INTERCEPTOR(long,strtol,const char * nptr,char ** endptr,int base)595 INTERCEPTOR(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 
INTERCEPTOR(int,atoi,const char * nptr)613 INTERCEPTOR(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 
INTERCEPTOR(long,atol,const char * nptr)632 INTERCEPTOR(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
INTERCEPTOR(long long,strtoll,const char * nptr,char ** endptr,int base)648 INTERCEPTOR(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 
INTERCEPTOR(long long,atoll,const char * nptr)669 INTERCEPTOR(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 
AtCxaAtexit(void * unused)682 static void AtCxaAtexit(void *unused) {
683   (void)unused;
684   StopInitOrderChecking();
685 }
686 
687 #if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)688 INTERCEPTOR(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
INTERCEPTOR(int,fork,void)701 INTERCEPTOR(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
INTERCEPTOR_WINAPI(DWORD,CreateThread,void * security,uptr stack_size,DWORD (__stdcall * start_routine)(void *),void * arg,DWORD thr_flags,void * tid)711 INTERCEPTOR_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 
728 namespace __asan {
InitializeWindowsInterceptors()729 void InitializeWindowsInterceptors() {
730   ASAN_INTERCEPT_FUNC(CreateThread);
731 }
732 
733 }  // namespace __asan
734 #endif
735 
736 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
737 namespace __asan {
InitializeAsanInterceptors()738 void 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