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