[gcc/testsuite]
[official-gcc.git] / libsanitizer / asan / asan_interceptors.cc
blob743abe51481340eba71fa14f446089186960c830
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 //===----------------------------------------------------------------------===//
13 #include "asan_interceptors.h"
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 "asan_suppressions.h"
22 #include "lsan/lsan_common.h"
23 #include "sanitizer_common/sanitizer_libc.h"
25 #if SANITIZER_POSIX
26 #include "sanitizer_common/sanitizer_posix.h"
27 #endif
29 #if defined(__i386) && SANITIZER_LINUX
30 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
31 #elif defined(__mips__) && SANITIZER_LINUX
32 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
33 #endif
35 namespace __asan {
37 // Return true if we can quickly decide that the region is unpoisoned.
38 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
39 if (size == 0) return true;
40 if (size <= 32)
41 return !AddressIsPoisoned(beg) &&
42 !AddressIsPoisoned(beg + size - 1) &&
43 !AddressIsPoisoned(beg + size / 2);
44 return false;
47 struct AsanInterceptorContext {
48 const char *interceptor_name;
51 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
52 // and ASAN_WRITE_RANGE as macro instead of function so
53 // that no extra frames are created, and stack trace contains
54 // relevant information only.
55 // We check all shadow bytes.
56 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
57 uptr __offset = (uptr)(offset); \
58 uptr __size = (uptr)(size); \
59 uptr __bad = 0; \
60 if (__offset > __offset + __size) { \
61 GET_STACK_TRACE_FATAL_HERE; \
62 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
63 } \
64 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
65 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
66 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
67 bool suppressed = false; \
68 if (_ctx) { \
69 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
70 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
71 GET_STACK_TRACE_FATAL_HERE; \
72 suppressed = IsStackTraceSuppressed(&stack); \
73 } \
74 } \
75 if (!suppressed) { \
76 GET_CURRENT_PC_BP_SP; \
77 ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
78 } \
79 } \
80 } while (0)
82 #define ASAN_READ_RANGE(ctx, offset, size) \
83 ACCESS_MEMORY_RANGE(ctx, offset, size, false)
84 #define ASAN_WRITE_RANGE(ctx, offset, size) \
85 ACCESS_MEMORY_RANGE(ctx, offset, size, true)
87 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
88 ASAN_READ_RANGE((ctx), (s), \
89 common_flags()->strict_string_checks ? (len) + 1 : (n))
91 #define ASAN_READ_STRING(ctx, s, n) \
92 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
94 // Behavior of functions like "memcpy" or "strcpy" is undefined
95 // if memory intervals overlap. We report error in this case.
96 // Macro is used to avoid creation of new frames.
97 static inline bool RangesOverlap(const char *offset1, uptr length1,
98 const char *offset2, uptr length2) {
99 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
101 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
102 const char *offset1 = (const char*)_offset1; \
103 const char *offset2 = (const char*)_offset2; \
104 if (RangesOverlap(offset1, length1, offset2, length2)) { \
105 GET_STACK_TRACE_FATAL_HERE; \
106 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
107 offset2, length2, &stack); \
109 } while (0)
111 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
112 #if SANITIZER_INTERCEPT_STRNLEN
113 if (REAL(strnlen)) {
114 return REAL(strnlen)(s, maxlen);
116 #endif
117 return internal_strnlen(s, maxlen);
120 void SetThreadName(const char *name) {
121 AsanThread *t = GetCurrentThread();
122 if (t)
123 asanThreadRegistry().SetThreadName(t->tid(), name);
126 int OnExit() {
127 // FIXME: ask frontend whether we need to return failure.
128 return 0;
131 } // namespace __asan
133 // ---------------------- Wrappers ---------------- {{{1
134 using namespace __asan; // NOLINT
136 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
137 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
139 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
140 AsanInterceptorContext _ctx = {#func}; \
141 ctx = (void *)&_ctx; \
142 (void) ctx; \
144 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
145 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
146 ASAN_INTERCEPT_FUNC_VER(name, ver)
147 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
148 ASAN_WRITE_RANGE(ctx, ptr, size)
149 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
150 ASAN_READ_RANGE(ctx, ptr, size)
151 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
152 ASAN_INTERCEPTOR_ENTER(ctx, func); \
153 do { \
154 if (asan_init_is_running) \
155 return REAL(func)(__VA_ARGS__); \
156 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
157 return REAL(func)(__VA_ARGS__); \
158 ENSURE_ASAN_INITED(); \
159 } while (false)
160 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
161 do { \
162 } while (false)
163 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
164 do { \
165 } while (false)
166 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
167 do { \
168 } while (false)
169 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
170 do { \
171 } while (false)
172 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
173 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
174 // But asan does not remember UserId's for threads (pthread_t);
175 // and remembers all ever existed threads, so the linear search by UserId
176 // can be slow.
177 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
178 do { \
179 } while (false)
180 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
181 // Strict init-order checking is dlopen-hostile:
182 // https://github.com/google/sanitizers/issues/178
183 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
184 if (flags()->strict_init_order) { \
185 StopInitOrderChecking(); \
187 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
188 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
189 CoverageUpdateMapping()
190 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
191 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
192 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
193 if (AsanThread *t = GetCurrentThread()) { \
194 *begin = t->tls_begin(); \
195 *end = t->tls_end(); \
196 } else { \
197 *begin = *end = 0; \
199 // Asan needs custom handling of these:
200 #undef SANITIZER_INTERCEPT_MEMSET
201 #undef SANITIZER_INTERCEPT_MEMMOVE
202 #undef SANITIZER_INTERCEPT_MEMCPY
203 #include "sanitizer_common/sanitizer_common_interceptors.inc"
205 // Syscall interceptors don't have contexts, we don't support suppressions
206 // for them.
207 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
208 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
209 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
210 do { \
211 (void)(p); \
212 (void)(s); \
213 } while (false)
214 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
215 do { \
216 (void)(p); \
217 (void)(s); \
218 } while (false)
219 #include "sanitizer_common/sanitizer_common_syscalls.inc"
221 struct ThreadStartParam {
222 atomic_uintptr_t t;
223 atomic_uintptr_t is_registered;
226 #if ASAN_INTERCEPT_PTHREAD_CREATE
227 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
228 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
229 AsanThread *t = nullptr;
230 while ((t = reinterpret_cast<AsanThread *>(
231 atomic_load(&param->t, memory_order_acquire))) == nullptr)
232 internal_sched_yield();
233 SetCurrentThread(t);
234 return t->ThreadStart(GetTid(), &param->is_registered);
237 INTERCEPTOR(int, pthread_create, void *thread,
238 void *attr, void *(*start_routine)(void*), void *arg) {
239 EnsureMainThreadIDIsCorrect();
240 // Strict init-order checking is thread-hostile.
241 if (flags()->strict_init_order)
242 StopInitOrderChecking();
243 GET_STACK_TRACE_THREAD;
244 int detached = 0;
245 if (attr)
246 REAL(pthread_attr_getdetachstate)(attr, &detached);
247 ThreadStartParam param;
248 atomic_store(&param.t, 0, memory_order_relaxed);
249 atomic_store(&param.is_registered, 0, memory_order_relaxed);
250 int result;
252 // Ignore all allocations made by pthread_create: thread stack/TLS may be
253 // stored by pthread for future reuse even after thread destruction, and
254 // the linked list it's stored in doesn't even hold valid pointers to the
255 // objects, the latter are calculated by obscure pointer arithmetic.
256 #if CAN_SANITIZE_LEAKS
257 __lsan::ScopedInterceptorDisabler disabler;
258 #endif
259 result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
261 if (result == 0) {
262 u32 current_tid = GetCurrentTidOrInvalid();
263 AsanThread *t =
264 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
265 atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
266 // Wait until the AsanThread object is initialized and the ThreadRegistry
267 // entry is in "started" state. One reason for this is that after this
268 // interceptor exits, the child thread's stack may be the only thing holding
269 // the |arg| pointer. This may cause LSan to report a leak if leak checking
270 // happens at a point when the interceptor has already exited, but the stack
271 // range for the child thread is not yet known.
272 while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
273 internal_sched_yield();
275 return result;
278 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
279 return real_pthread_join(t, arg);
282 DEFINE_REAL_PTHREAD_FUNCTIONS
283 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
285 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
287 #if SANITIZER_ANDROID
288 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
289 if (!IsHandledDeadlySignal(signum) ||
290 common_flags()->allow_user_segv_handler) {
291 return REAL(bsd_signal)(signum, handler);
293 return 0;
295 #endif
297 INTERCEPTOR(void*, signal, int signum, void *handler) {
298 if (!IsHandledDeadlySignal(signum) ||
299 common_flags()->allow_user_segv_handler) {
300 return REAL(signal)(signum, handler);
302 return nullptr;
305 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
306 struct sigaction *oldact) {
307 if (!IsHandledDeadlySignal(signum) ||
308 common_flags()->allow_user_segv_handler) {
309 return REAL(sigaction)(signum, act, oldact);
311 return 0;
314 namespace __sanitizer {
315 int real_sigaction(int signum, const void *act, void *oldact) {
316 return REAL(sigaction)(signum, (const struct sigaction *)act,
317 (struct sigaction *)oldact);
319 } // namespace __sanitizer
321 #elif SANITIZER_POSIX
322 // We need to have defined REAL(sigaction) on posix systems.
323 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
324 struct sigaction *oldact)
325 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
327 #if ASAN_INTERCEPT_SWAPCONTEXT
328 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
329 // Align to page size.
330 uptr PageSize = GetPageSizeCached();
331 uptr bottom = stack & ~(PageSize - 1);
332 ssize += stack - bottom;
333 ssize = RoundUpTo(ssize, PageSize);
334 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
335 if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
336 PoisonShadow(bottom, ssize, 0);
340 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
341 struct ucontext_t *ucp) {
342 static bool reported_warning = false;
343 if (!reported_warning) {
344 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
345 "functions and may produce false positives in some cases!\n");
346 reported_warning = true;
348 // Clear shadow memory for new context (it may share stack
349 // with current context).
350 uptr stack, ssize;
351 ReadContextStack(ucp, &stack, &ssize);
352 ClearShadowMemoryForContextStack(stack, ssize);
353 int res = REAL(swapcontext)(oucp, ucp);
354 // swapcontext technically does not return, but program may swap context to
355 // "oucp" later, that would look as if swapcontext() returned 0.
356 // We need to clear shadow for ucp once again, as it may be in arbitrary
357 // state.
358 ClearShadowMemoryForContextStack(stack, ssize);
359 return res;
361 #endif // ASAN_INTERCEPT_SWAPCONTEXT
363 INTERCEPTOR(void, longjmp, void *env, int val) {
364 __asan_handle_no_return();
365 REAL(longjmp)(env, val);
368 #if ASAN_INTERCEPT__LONGJMP
369 INTERCEPTOR(void, _longjmp, void *env, int val) {
370 __asan_handle_no_return();
371 REAL(_longjmp)(env, val);
373 #endif
375 #if ASAN_INTERCEPT_SIGLONGJMP
376 INTERCEPTOR(void, siglongjmp, void *env, int val) {
377 __asan_handle_no_return();
378 REAL(siglongjmp)(env, val);
380 #endif
382 #if ASAN_INTERCEPT___CXA_THROW
383 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
384 CHECK(REAL(__cxa_throw));
385 __asan_handle_no_return();
386 REAL(__cxa_throw)(a, b, c);
388 #endif
390 // memcpy is called during __asan_init() from the internals of printf(...).
391 // We do not treat memcpy with to==from as a bug.
392 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
393 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
394 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
395 if (asan_init_is_running) { \
396 return REAL(memcpy)(to, from, size); \
398 ENSURE_ASAN_INITED(); \
399 if (flags()->replace_intrin) { \
400 if (to != from) { \
401 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
403 ASAN_READ_RANGE(ctx, from, size); \
404 ASAN_WRITE_RANGE(ctx, to, size); \
406 return REAL(memcpy)(to, from, size); \
407 } while (0)
410 void *__asan_memcpy(void *to, const void *from, uptr size) {
411 ASAN_MEMCPY_IMPL(nullptr, to, from, size);
414 // memset is called inside Printf.
415 #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
416 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
417 if (asan_init_is_running) { \
418 return REAL(memset)(block, c, size); \
420 ENSURE_ASAN_INITED(); \
421 if (flags()->replace_intrin) { \
422 ASAN_WRITE_RANGE(ctx, block, size); \
424 return REAL(memset)(block, c, size); \
425 } while (0)
427 void *__asan_memset(void *block, int c, uptr size) {
428 ASAN_MEMSET_IMPL(nullptr, block, c, size);
431 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
432 if (UNLIKELY(!asan_inited)) \
433 return internal_memmove(to, from, size); \
434 ENSURE_ASAN_INITED(); \
435 if (flags()->replace_intrin) { \
436 ASAN_READ_RANGE(ctx, from, size); \
437 ASAN_WRITE_RANGE(ctx, to, size); \
439 return internal_memmove(to, from, size); \
440 } while (0)
442 void *__asan_memmove(void *to, const void *from, uptr size) {
443 ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
446 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
447 void *ctx;
448 ASAN_INTERCEPTOR_ENTER(ctx, memmove);
449 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
452 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
453 void *ctx;
454 ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
455 #if !SANITIZER_MAC
456 ASAN_MEMCPY_IMPL(ctx, to, from, size);
457 #else
458 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
459 // with WRAP(memcpy). As a result, false positives are reported for memmove()
460 // calls. If we just disable error reporting with
461 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
462 // internal_memcpy(), which may lead to crashes, see
463 // http://llvm.org/bugs/show_bug.cgi?id=16362.
464 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
465 #endif // !SANITIZER_MAC
468 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
469 void *ctx;
470 ASAN_INTERCEPTOR_ENTER(ctx, memset);
471 ASAN_MEMSET_IMPL(ctx, block, c, size);
474 #if ASAN_INTERCEPT_INDEX
475 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
476 INTERCEPTOR(char*, index, const char *string, int c)
477 ALIAS(WRAPPER_NAME(strchr));
478 # else
479 # if SANITIZER_MAC
480 DECLARE_REAL(char*, index, const char *string, int c)
481 OVERRIDE_FUNCTION(index, strchr);
482 # else
483 DEFINE_REAL(char*, index, const char *string, int c)
484 # endif
485 # endif
486 #endif // ASAN_INTERCEPT_INDEX
488 // For both strcat() and strncat() we need to check the validity of |to|
489 // argument irrespective of the |from| length.
490 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
491 void *ctx;
492 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
493 ENSURE_ASAN_INITED();
494 if (flags()->replace_str) {
495 uptr from_length = REAL(strlen)(from);
496 ASAN_READ_RANGE(ctx, from, from_length + 1);
497 uptr to_length = REAL(strlen)(to);
498 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
499 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
500 // If the copying actually happens, the |from| string should not overlap
501 // with the resulting string starting at |to|, which has a length of
502 // to_length + from_length + 1.
503 if (from_length > 0) {
504 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
505 from, from_length + 1);
508 return REAL(strcat)(to, from); // NOLINT
511 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
512 void *ctx;
513 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
514 ENSURE_ASAN_INITED();
515 if (flags()->replace_str) {
516 uptr from_length = MaybeRealStrnlen(from, size);
517 uptr copy_length = Min(size, from_length + 1);
518 ASAN_READ_RANGE(ctx, from, copy_length);
519 uptr to_length = REAL(strlen)(to);
520 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
521 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
522 if (from_length > 0) {
523 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
524 from, copy_length);
527 return REAL(strncat)(to, from, size);
530 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
531 void *ctx;
532 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
533 #if SANITIZER_MAC
534 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
535 #endif
536 // strcpy is called from malloc_default_purgeable_zone()
537 // in __asan::ReplaceSystemAlloc() on Mac.
538 if (asan_init_is_running) {
539 return REAL(strcpy)(to, from); // NOLINT
541 ENSURE_ASAN_INITED();
542 if (flags()->replace_str) {
543 uptr from_size = REAL(strlen)(from) + 1;
544 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
545 ASAN_READ_RANGE(ctx, from, from_size);
546 ASAN_WRITE_RANGE(ctx, to, from_size);
548 return REAL(strcpy)(to, from); // NOLINT
551 INTERCEPTOR(char*, strdup, const char *s) {
552 void *ctx;
553 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
554 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
555 ENSURE_ASAN_INITED();
556 uptr length = REAL(strlen)(s);
557 if (flags()->replace_str) {
558 ASAN_READ_RANGE(ctx, s, length + 1);
560 GET_STACK_TRACE_MALLOC;
561 void *new_mem = asan_malloc(length + 1, &stack);
562 REAL(memcpy)(new_mem, s, length + 1);
563 return reinterpret_cast<char*>(new_mem);
566 #if ASAN_INTERCEPT___STRDUP
567 INTERCEPTOR(char*, __strdup, const char *s) {
568 void *ctx;
569 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
570 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
571 ENSURE_ASAN_INITED();
572 uptr length = REAL(strlen)(s);
573 if (flags()->replace_str) {
574 ASAN_READ_RANGE(ctx, s, length + 1);
576 GET_STACK_TRACE_MALLOC;
577 void *new_mem = asan_malloc(length + 1, &stack);
578 REAL(memcpy)(new_mem, s, length + 1);
579 return reinterpret_cast<char*>(new_mem);
581 #endif // ASAN_INTERCEPT___STRDUP
583 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
584 void *ctx;
585 ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
586 SIZE_T length = internal_wcslen(s);
587 if (!asan_init_is_running) {
588 ENSURE_ASAN_INITED();
589 ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
591 return length;
594 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
595 void *ctx;
596 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
597 ENSURE_ASAN_INITED();
598 if (flags()->replace_str) {
599 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
600 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
601 ASAN_READ_RANGE(ctx, from, from_size);
602 ASAN_WRITE_RANGE(ctx, to, size);
604 return REAL(strncpy)(to, from, size);
607 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
608 char **endptr, int base) {
609 void *ctx;
610 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
611 ENSURE_ASAN_INITED();
612 if (!flags()->replace_str) {
613 return REAL(strtol)(nptr, endptr, base);
615 char *real_endptr;
616 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
617 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
618 return result;
621 INTERCEPTOR(int, atoi, const char *nptr) {
622 void *ctx;
623 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
624 #if SANITIZER_MAC
625 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
626 #endif
627 ENSURE_ASAN_INITED();
628 if (!flags()->replace_str) {
629 return REAL(atoi)(nptr);
631 char *real_endptr;
632 // "man atoi" tells that behavior of atoi(nptr) is the same as
633 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
634 // parsed integer can't be stored in *long* type (even if it's
635 // different from int). So, we just imitate this behavior.
636 int result = REAL(strtol)(nptr, &real_endptr, 10);
637 FixRealStrtolEndptr(nptr, &real_endptr);
638 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
639 return result;
642 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
643 void *ctx;
644 ASAN_INTERCEPTOR_ENTER(ctx, atol);
645 #if SANITIZER_MAC
646 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
647 #endif
648 ENSURE_ASAN_INITED();
649 if (!flags()->replace_str) {
650 return REAL(atol)(nptr);
652 char *real_endptr;
653 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
654 FixRealStrtolEndptr(nptr, &real_endptr);
655 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
656 return result;
659 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
660 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
661 char **endptr, int base) {
662 void *ctx;
663 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
664 ENSURE_ASAN_INITED();
665 if (!flags()->replace_str) {
666 return REAL(strtoll)(nptr, endptr, base);
668 char *real_endptr;
669 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
670 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
671 return result;
674 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
675 void *ctx;
676 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
677 ENSURE_ASAN_INITED();
678 if (!flags()->replace_str) {
679 return REAL(atoll)(nptr);
681 char *real_endptr;
682 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
683 FixRealStrtolEndptr(nptr, &real_endptr);
684 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
685 return result;
687 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
689 #if ASAN_INTERCEPT___CXA_ATEXIT
690 static void AtCxaAtexit(void *unused) {
691 (void)unused;
692 StopInitOrderChecking();
695 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
696 void *dso_handle) {
697 #if SANITIZER_MAC
698 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
699 #endif
700 ENSURE_ASAN_INITED();
701 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
702 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
703 return res;
705 #endif // ASAN_INTERCEPT___CXA_ATEXIT
707 #if ASAN_INTERCEPT_FORK
708 INTERCEPTOR(int, fork, void) {
709 ENSURE_ASAN_INITED();
710 if (common_flags()->coverage) CovBeforeFork();
711 int pid = REAL(fork)();
712 if (common_flags()->coverage) CovAfterFork(pid);
713 return pid;
715 #endif // ASAN_INTERCEPT_FORK
717 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
718 namespace __asan {
719 void InitializeAsanInterceptors() {
720 static bool was_called_once;
721 CHECK(!was_called_once);
722 was_called_once = true;
723 InitializeCommonInterceptors();
725 // Intercept mem* functions.
726 ASAN_INTERCEPT_FUNC(memmove);
727 ASAN_INTERCEPT_FUNC(memset);
728 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
729 // In asan, REAL(memmove) is not used, but it is used in msan.
730 ASAN_INTERCEPT_FUNC(memcpy);
731 } else {
732 ASSIGN_REAL(memcpy, memmove);
734 CHECK(REAL(memcpy));
736 // Intercept str* functions.
737 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
738 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
739 ASAN_INTERCEPT_FUNC(wcslen);
740 ASAN_INTERCEPT_FUNC(strncat);
741 ASAN_INTERCEPT_FUNC(strncpy);
742 ASAN_INTERCEPT_FUNC(strdup);
743 #if ASAN_INTERCEPT___STRDUP
744 ASAN_INTERCEPT_FUNC(__strdup);
745 #endif
746 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
747 ASAN_INTERCEPT_FUNC(index);
748 #endif
750 ASAN_INTERCEPT_FUNC(atoi);
751 ASAN_INTERCEPT_FUNC(atol);
752 ASAN_INTERCEPT_FUNC(strtol);
753 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
754 ASAN_INTERCEPT_FUNC(atoll);
755 ASAN_INTERCEPT_FUNC(strtoll);
756 #endif
758 // Intecept signal- and jump-related functions.
759 ASAN_INTERCEPT_FUNC(longjmp);
760 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
761 ASAN_INTERCEPT_FUNC(sigaction);
762 #if SANITIZER_ANDROID
763 ASAN_INTERCEPT_FUNC(bsd_signal);
764 #endif
765 ASAN_INTERCEPT_FUNC(signal);
766 #endif
767 #if ASAN_INTERCEPT_SWAPCONTEXT
768 ASAN_INTERCEPT_FUNC(swapcontext);
769 #endif
770 #if ASAN_INTERCEPT__LONGJMP
771 ASAN_INTERCEPT_FUNC(_longjmp);
772 #endif
773 #if ASAN_INTERCEPT_SIGLONGJMP
774 ASAN_INTERCEPT_FUNC(siglongjmp);
775 #endif
777 // Intercept exception handling functions.
778 #if ASAN_INTERCEPT___CXA_THROW
779 ASAN_INTERCEPT_FUNC(__cxa_throw);
780 #endif
782 // Intercept threading-related functions
783 #if ASAN_INTERCEPT_PTHREAD_CREATE
784 #if defined(ASAN_PTHREAD_CREATE_VERSION)
785 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
786 #else
787 ASAN_INTERCEPT_FUNC(pthread_create);
788 #endif
789 ASAN_INTERCEPT_FUNC(pthread_join);
790 #endif
792 // Intercept atexit function.
793 #if ASAN_INTERCEPT___CXA_ATEXIT
794 ASAN_INTERCEPT_FUNC(__cxa_atexit);
795 #endif
797 #if ASAN_INTERCEPT_FORK
798 ASAN_INTERCEPT_FUNC(fork);
799 #endif
801 InitializePlatformInterceptors();
803 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
806 } // namespace __asan