xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/asan/asan_interceptors.cc (revision 7c192b2a5e1093666e67801684f930ef49b3b363)
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 
23 namespace __asan {
24 
25 // Return true if we can quickly decide that the region is unpoisoned.
26 static 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.
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 static 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 
84 void SetThreadName(const char *name) {
85   AsanThread *t = GetCurrentThread();
86   if (t)
87     asanThreadRegistry().SetThreadName(t->tid(), name);
88 }
89 
90 int OnExit() {
91   // FIXME: ask frontend whether we need to return failure.
92   return 0;
93 }
94 
95 }  // namespace __asan
96 
97 // ---------------------- Wrappers ---------------- {{{1
98 using namespace __asan;  // NOLINT
99 
100 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
101 DECLARE_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 
166 static 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
173 INTERCEPTOR(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
195 INTERCEPTOR(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
203 INTERCEPTOR(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 
212 INTERCEPTOR(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 
221 namespace __sanitizer {
222 int 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.
230 DEFINE_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
235 static 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 
247 INTERCEPTOR(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 
270 #if SANITIZER_NETBSD
271 #define longjmp __longjmp14
272 #define siglongjmp __siglongjmp14
273 #endif
274 
275 INTERCEPTOR(void, longjmp, void *env, int val) {
276   __asan_handle_no_return();
277   REAL(longjmp)(env, val);
278 }
279 
280 #if ASAN_INTERCEPT__LONGJMP
281 INTERCEPTOR(void, _longjmp, void *env, int val) {
282   __asan_handle_no_return();
283   REAL(_longjmp)(env, val);
284 }
285 #endif
286 
287 #if ASAN_INTERCEPT_SIGLONGJMP
288 INTERCEPTOR(void, siglongjmp, void *env, int val) {
289   __asan_handle_no_return();
290   REAL(siglongjmp)(env, val);
291 }
292 #endif
293 
294 #if ASAN_INTERCEPT___CXA_THROW
295 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
296   CHECK(REAL(__cxa_throw));
297   __asan_handle_no_return();
298   REAL(__cxa_throw)(a, b, c);
299 }
300 #endif
301 
302 #if SANITIZER_WINDOWS
303 INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
304   CHECK(REAL(RaiseException));
305   __asan_handle_no_return();
306   REAL(RaiseException)(a, b, c, d);
307 }
308 
309 INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
310   CHECK(REAL(_except_handler3));
311   __asan_handle_no_return();
312   return REAL(_except_handler3)(a, b, c, d);
313 }
314 
315 #if ASAN_DYNAMIC
316 // This handler is named differently in -MT and -MD CRTs.
317 #define _except_handler4 _except_handler4_common
318 #endif
319 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
320   CHECK(REAL(_except_handler4));
321   __asan_handle_no_return();
322   return REAL(_except_handler4)(a, b, c, d);
323 }
324 #endif
325 
326 static inline int CharCmp(unsigned char c1, unsigned char c2) {
327   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
328 }
329 
330 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
331   if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
332   ENSURE_ASAN_INITED();
333   if (flags()->replace_intrin) {
334     if (flags()->strict_memcmp) {
335       // Check the entire regions even if the first bytes of the buffers are
336       // different.
337       ASAN_READ_RANGE(a1, size);
338       ASAN_READ_RANGE(a2, size);
339       // Fallthrough to REAL(memcmp) below.
340     } else {
341       unsigned char c1 = 0, c2 = 0;
342       const unsigned char *s1 = (const unsigned char*)a1;
343       const unsigned char *s2 = (const unsigned char*)a2;
344       uptr i;
345       for (i = 0; i < size; i++) {
346         c1 = s1[i];
347         c2 = s2[i];
348         if (c1 != c2) break;
349       }
350       ASAN_READ_RANGE(s1, Min(i + 1, size));
351       ASAN_READ_RANGE(s2, Min(i + 1, size));
352       return CharCmp(c1, c2);
353     }
354   }
355   return REAL(memcmp(a1, a2, size));
356 }
357 
358 void *__asan_memcpy(void *to, const void *from, uptr size) {
359   if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);
360   // memcpy is called during __asan_init() from the internals
361   // of printf(...).
362   if (asan_init_is_running) {
363     return REAL(memcpy)(to, from, size);
364   }
365   ENSURE_ASAN_INITED();
366   if (flags()->replace_intrin) {
367     if (to != from) {
368       // We do not treat memcpy with to==from as a bug.
369       // See http://llvm.org/bugs/show_bug.cgi?id=11763.
370       CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
371     }
372     ASAN_READ_RANGE(from, size);
373     ASAN_WRITE_RANGE(to, size);
374   }
375   return REAL(memcpy)(to, from, size);
376 }
377 
378 void *__asan_memset(void *block, int c, uptr size) {
379   if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);
380   // memset is called inside Printf.
381   if (asan_init_is_running) {
382     return REAL(memset)(block, c, size);
383   }
384   ENSURE_ASAN_INITED();
385   if (flags()->replace_intrin) {
386     ASAN_WRITE_RANGE(block, size);
387   }
388   return REAL(memset)(block, c, size);
389 }
390 
391 void *__asan_memmove(void *to, const void *from, uptr size) {
392   if (UNLIKELY(!asan_inited))
393     return internal_memmove(to, from, size);
394   ENSURE_ASAN_INITED();
395   if (flags()->replace_intrin) {
396     ASAN_READ_RANGE(from, size);
397     ASAN_WRITE_RANGE(to, size);
398   }
399   return internal_memmove(to, from, size);
400 }
401 
402 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
403   return __asan_memmove(to, from, size);
404 }
405 
406 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
407 #if !SANITIZER_MAC
408   return __asan_memcpy(to, from, size);
409 #else
410   // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
411   // with WRAP(memcpy). As a result, false positives are reported for memmove()
412   // calls. If we just disable error reporting with
413   // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
414   // internal_memcpy(), which may lead to crashes, see
415   // http://llvm.org/bugs/show_bug.cgi?id=16362.
416   return __asan_memmove(to, from, size);
417 #endif  // !SANITIZER_MAC
418 }
419 
420 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
421   return __asan_memset(block, c, size);
422 }
423 
424 INTERCEPTOR(char*, strchr, const char *str, int c) {
425   if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
426   // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
427   // used.
428   if (asan_init_is_running) {
429     return REAL(strchr)(str, c);
430   }
431   ENSURE_ASAN_INITED();
432   char *result = REAL(strchr)(str, c);
433   if (flags()->replace_str) {
434     uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
435     ASAN_READ_RANGE(str, bytes_read);
436   }
437   return result;
438 }
439 
440 #if ASAN_INTERCEPT_INDEX
441 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
442 INTERCEPTOR(char*, index, const char *string, int c)
443   ALIAS(WRAPPER_NAME(strchr));
444 # else
445 #  if SANITIZER_MAC
446 DECLARE_REAL(char*, index, const char *string, int c)
447 OVERRIDE_FUNCTION(index, strchr);
448 #  else
449 DEFINE_REAL(char*, index, const char *string, int c)
450 #  endif
451 # endif
452 #endif  // ASAN_INTERCEPT_INDEX
453 
454 // For both strcat() and strncat() we need to check the validity of |to|
455 // argument irrespective of the |from| length.
456 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
457   ENSURE_ASAN_INITED();
458   if (flags()->replace_str) {
459     uptr from_length = REAL(strlen)(from);
460     ASAN_READ_RANGE(from, from_length + 1);
461     uptr to_length = REAL(strlen)(to);
462     ASAN_READ_RANGE(to, to_length);
463     ASAN_WRITE_RANGE(to + to_length, from_length + 1);
464     // If the copying actually happens, the |from| string should not overlap
465     // with the resulting string starting at |to|, which has a length of
466     // to_length + from_length + 1.
467     if (from_length > 0) {
468       CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
469                            from, from_length + 1);
470     }
471   }
472   return REAL(strcat)(to, from);  // NOLINT
473 }
474 
475 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
476   ENSURE_ASAN_INITED();
477   if (flags()->replace_str) {
478     uptr from_length = MaybeRealStrnlen(from, size);
479     uptr copy_length = Min(size, from_length + 1);
480     ASAN_READ_RANGE(from, copy_length);
481     uptr to_length = REAL(strlen)(to);
482     ASAN_READ_RANGE(to, to_length);
483     ASAN_WRITE_RANGE(to + to_length, from_length + 1);
484     if (from_length > 0) {
485       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
486                            from, copy_length);
487     }
488   }
489   return REAL(strncat)(to, from, size);
490 }
491 
492 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
493 #if SANITIZER_MAC
494   if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
495 #endif
496   // strcpy is called from malloc_default_purgeable_zone()
497   // in __asan::ReplaceSystemAlloc() on Mac.
498   if (asan_init_is_running) {
499     return REAL(strcpy)(to, from);  // NOLINT
500   }
501   ENSURE_ASAN_INITED();
502   if (flags()->replace_str) {
503     uptr from_size = REAL(strlen)(from) + 1;
504     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
505     ASAN_READ_RANGE(from, from_size);
506     ASAN_WRITE_RANGE(to, from_size);
507   }
508   return REAL(strcpy)(to, from);  // NOLINT
509 }
510 
511 #if ASAN_INTERCEPT_STRDUP
512 INTERCEPTOR(char*, strdup, const char *s) {
513   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
514   ENSURE_ASAN_INITED();
515   uptr length = REAL(strlen)(s);
516   if (flags()->replace_str) {
517     ASAN_READ_RANGE(s, length + 1);
518   }
519   GET_STACK_TRACE_MALLOC;
520   void *new_mem = asan_malloc(length + 1, &stack);
521   REAL(memcpy)(new_mem, s, length + 1);
522   return reinterpret_cast<char*>(new_mem);
523 }
524 #endif
525 
526 INTERCEPTOR(SIZE_T, strlen, const char *s) {
527   if (UNLIKELY(!asan_inited)) return internal_strlen(s);
528   // strlen is called from malloc_default_purgeable_zone()
529   // in __asan::ReplaceSystemAlloc() on Mac.
530   if (asan_init_is_running) {
531     return REAL(strlen)(s);
532   }
533   ENSURE_ASAN_INITED();
534   SIZE_T length = REAL(strlen)(s);
535   if (flags()->replace_str) {
536     ASAN_READ_RANGE(s, length + 1);
537   }
538   return length;
539 }
540 
541 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
542   SIZE_T length = REAL(wcslen)(s);
543   if (!asan_init_is_running) {
544     ENSURE_ASAN_INITED();
545     ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
546   }
547   return length;
548 }
549 
550 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
551   ENSURE_ASAN_INITED();
552   if (flags()->replace_str) {
553     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
554     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
555     ASAN_READ_RANGE(from, from_size);
556     ASAN_WRITE_RANGE(to, size);
557   }
558   return REAL(strncpy)(to, from, size);
559 }
560 
561 #if ASAN_INTERCEPT_STRNLEN
562 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
563   ENSURE_ASAN_INITED();
564   uptr length = REAL(strnlen)(s, maxlen);
565   if (flags()->replace_str) {
566     ASAN_READ_RANGE(s, Min(length + 1, maxlen));
567   }
568   return length;
569 }
570 #endif  // ASAN_INTERCEPT_STRNLEN
571 
572 static inline bool IsValidStrtolBase(int base) {
573   return (base == 0) || (2 <= base && base <= 36);
574 }
575 
576 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
577   CHECK(endptr);
578   if (nptr == *endptr) {
579     // No digits were found at strtol call, we need to find out the last
580     // symbol accessed by strtoll on our own.
581     // We get this symbol by skipping leading blanks and optional +/- sign.
582     while (IsSpace(*nptr)) nptr++;
583     if (*nptr == '+' || *nptr == '-') nptr++;
584     *endptr = (char*)nptr;
585   }
586   CHECK(*endptr >= nptr);
587 }
588 
589 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
590             char **endptr, int base) {
591   ENSURE_ASAN_INITED();
592   if (!flags()->replace_str) {
593     return REAL(strtol)(nptr, endptr, base);
594   }
595   char *real_endptr;
596   long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
597   if (endptr != 0) {
598     *endptr = real_endptr;
599   }
600   if (IsValidStrtolBase(base)) {
601     FixRealStrtolEndptr(nptr, &real_endptr);
602     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
603   }
604   return result;
605 }
606 
607 INTERCEPTOR(int, atoi, const char *nptr) {
608 #if SANITIZER_MAC
609   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
610 #endif
611   ENSURE_ASAN_INITED();
612   if (!flags()->replace_str) {
613     return REAL(atoi)(nptr);
614   }
615   char *real_endptr;
616   // "man atoi" tells that behavior of atoi(nptr) is the same as
617   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
618   // parsed integer can't be stored in *long* type (even if it's
619   // different from int). So, we just imitate this behavior.
620   int result = REAL(strtol)(nptr, &real_endptr, 10);
621   FixRealStrtolEndptr(nptr, &real_endptr);
622   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
623   return result;
624 }
625 
626 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
627 #if SANITIZER_MAC
628   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
629 #endif
630   ENSURE_ASAN_INITED();
631   if (!flags()->replace_str) {
632     return REAL(atol)(nptr);
633   }
634   char *real_endptr;
635   long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
636   FixRealStrtolEndptr(nptr, &real_endptr);
637   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
638   return result;
639 }
640 
641 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
642 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
643             char **endptr, int base) {
644   ENSURE_ASAN_INITED();
645   if (!flags()->replace_str) {
646     return REAL(strtoll)(nptr, endptr, base);
647   }
648   char *real_endptr;
649   long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
650   if (endptr != 0) {
651     *endptr = real_endptr;
652   }
653   // If base has unsupported value, strtoll can exit with EINVAL
654   // without reading any characters. So do additional checks only
655   // if base is valid.
656   if (IsValidStrtolBase(base)) {
657     FixRealStrtolEndptr(nptr, &real_endptr);
658     ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
659   }
660   return result;
661 }
662 
663 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
664   ENSURE_ASAN_INITED();
665   if (!flags()->replace_str) {
666     return REAL(atoll)(nptr);
667   }
668   char *real_endptr;
669   long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
670   FixRealStrtolEndptr(nptr, &real_endptr);
671   ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
672   return result;
673 }
674 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
675 
676 static void AtCxaAtexit(void *unused) {
677   (void)unused;
678   StopInitOrderChecking();
679 }
680 
681 #if ASAN_INTERCEPT___CXA_ATEXIT
682 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
683             void *dso_handle) {
684 #if SANITIZER_MAC
685   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
686 #endif
687   ENSURE_ASAN_INITED();
688   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
689   REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
690   return res;
691 }
692 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
693 
694 #if ASAN_INTERCEPT_FORK
695 INTERCEPTOR(int, fork, void) {
696   ENSURE_ASAN_INITED();
697   if (common_flags()->coverage) CovBeforeFork();
698   int pid = REAL(fork)();
699   if (common_flags()->coverage) CovAfterFork(pid);
700   return pid;
701 }
702 #endif  // ASAN_INTERCEPT_FORK
703 
704 #if SANITIZER_WINDOWS
705 INTERCEPTOR_WINAPI(DWORD, CreateThread,
706                    void* security, uptr stack_size,
707                    DWORD (__stdcall *start_routine)(void*), void* arg,
708                    DWORD thr_flags, void* tid) {
709   // Strict init-order checking in thread-hostile.
710   if (flags()->strict_init_order)
711     StopInitOrderChecking();
712   GET_STACK_TRACE_THREAD;
713   u32 current_tid = GetCurrentTidOrInvalid();
714   AsanThread *t = AsanThread::Create(start_routine, arg);
715   CreateThreadContextArgs args = { t, &stack };
716   bool detached = false;  // FIXME: how can we determine it on Windows?
717   asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
718   return REAL(CreateThread)(security, stack_size,
719                             asan_thread_start, t, thr_flags, tid);
720 }
721 
722 namespace __asan {
723 void InitializeWindowsInterceptors() {
724   ASAN_INTERCEPT_FUNC(CreateThread);
725   ASAN_INTERCEPT_FUNC(RaiseException);
726   ASAN_INTERCEPT_FUNC(_except_handler3);
727   ASAN_INTERCEPT_FUNC(_except_handler4);
728 }
729 
730 }  // namespace __asan
731 #endif
732 
733 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
734 namespace __asan {
735 void InitializeAsanInterceptors() {
736   static bool was_called_once;
737   CHECK(was_called_once == false);
738   was_called_once = true;
739   InitializeCommonInterceptors();
740 
741   // Intercept mem* functions.
742   ASAN_INTERCEPT_FUNC(memcmp);
743   ASAN_INTERCEPT_FUNC(memmove);
744   ASAN_INTERCEPT_FUNC(memset);
745   if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
746     ASAN_INTERCEPT_FUNC(memcpy);
747   }
748 
749   // Intercept str* functions.
750   ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
751   ASAN_INTERCEPT_FUNC(strchr);
752   ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
753   ASAN_INTERCEPT_FUNC(strlen);
754   ASAN_INTERCEPT_FUNC(wcslen);
755   ASAN_INTERCEPT_FUNC(strncat);
756   ASAN_INTERCEPT_FUNC(strncpy);
757 #if ASAN_INTERCEPT_STRDUP
758   ASAN_INTERCEPT_FUNC(strdup);
759 #endif
760 #if ASAN_INTERCEPT_STRNLEN
761   ASAN_INTERCEPT_FUNC(strnlen);
762 #endif
763 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
764   ASAN_INTERCEPT_FUNC(index);
765 #endif
766 
767   ASAN_INTERCEPT_FUNC(atoi);
768   ASAN_INTERCEPT_FUNC(atol);
769   ASAN_INTERCEPT_FUNC(strtol);
770 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
771   ASAN_INTERCEPT_FUNC(atoll);
772   ASAN_INTERCEPT_FUNC(strtoll);
773 #endif
774 
775   // Intecept signal- and jump-related functions.
776   ASAN_INTERCEPT_FUNC(longjmp);
777 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
778   ASAN_INTERCEPT_FUNC(sigaction);
779 #if SANITIZER_ANDROID
780   ASAN_INTERCEPT_FUNC(bsd_signal);
781 #else
782   ASAN_INTERCEPT_FUNC(signal);
783 #endif
784 #endif
785 #if ASAN_INTERCEPT_SWAPCONTEXT
786   ASAN_INTERCEPT_FUNC(swapcontext);
787 #endif
788 #if ASAN_INTERCEPT__LONGJMP
789   ASAN_INTERCEPT_FUNC(_longjmp);
790 #endif
791 #if ASAN_INTERCEPT_SIGLONGJMP
792   ASAN_INTERCEPT_FUNC(siglongjmp);
793 #endif
794 
795   // Intercept exception handling functions.
796 #if ASAN_INTERCEPT___CXA_THROW
797   ASAN_INTERCEPT_FUNC(__cxa_throw);
798 #endif
799 
800   // Intercept threading-related functions
801 #if ASAN_INTERCEPT_PTHREAD_CREATE
802   ASAN_INTERCEPT_FUNC(pthread_create);
803 #endif
804 
805   // Intercept atexit function.
806 #if ASAN_INTERCEPT___CXA_ATEXIT
807   ASAN_INTERCEPT_FUNC(__cxa_atexit);
808 #endif
809 
810 #if ASAN_INTERCEPT_FORK
811   ASAN_INTERCEPT_FUNC(fork);
812 #endif
813 
814   // Some Windows-specific interceptors.
815 #if SANITIZER_WINDOWS
816   InitializeWindowsInterceptors();
817 #endif
818 
819   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
820 }
821 
822 }  // namespace __asan
823