1 //===-- asan_interceptors.cc ------------------------------------*- C++ -*-===//
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_interface.h"
18 #include "asan_internal.h"
19 #include "asan_mapping.h"
20 #include "asan_stack.h"
21 #include "asan_stats.h"
22 #include "asan_thread_registry.h"
23 #include "interception/interception.h"
24
25 // Use macro to describe if specific function should be
26 // intercepted on a given platform.
27 #if !defined(_WIN32)
28 # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
29 #else
30 # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
31 #endif
32
33 #if !defined(__APPLE__)
34 # define ASAN_INTERCEPT_STRNLEN 1
35 #else
36 # define ASAN_INTERCEPT_STRNLEN 0
37 #endif
38
39 #if defined(ANDROID) || defined(_WIN32)
40 # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
41 #else
42 # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
43 #endif
44
45 // Use extern declarations of intercepted functions on Mac and Windows
46 // to avoid including system headers.
47 #if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
48 extern "C" {
49 // signal.h
50 # if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
51 struct sigaction;
52 int sigaction(int sig, const struct sigaction *act,
53 struct sigaction *oldact);
54 void *signal(int signum, void *handler);
55 # endif
56
57 // setjmp.h
58 void longjmp(void* env, int value);
59 # if !defined(_WIN32)
60 void _longjmp(void *env, int value);
61 # endif
62
63 // string.h / strings.h
64 int memcmp(const void *a1, const void *a2, size_t size);
65 void* memmove(void *to, const void *from, size_t size);
66 void* memcpy(void *to, const void *from, size_t size);
67 void* memset(void *block, int c, size_t size);
68 char* strchr(const char *str, int c);
69 # if defined(__APPLE__)
70 char* index(const char *string, int c);
71 # endif
72 char* strcat(char *to, const char* from); // NOLINT
73 char* strcpy(char *to, const char* from); // NOLINT
74 char* strncpy(char *to, const char* from, size_t size);
75 int strcmp(const char *s1, const char* s2);
76 int strncmp(const char *s1, const char* s2, size_t size);
77 # if !defined(_WIN32)
78 int strcasecmp(const char *s1, const char *s2);
79 int strncasecmp(const char *s1, const char *s2, size_t n);
80 char* strdup(const char *s);
81 # endif
82 size_t strlen(const char *s);
83 # if ASAN_INTERCEPT_STRNLEN
84 size_t strnlen(const char *s, size_t maxlen);
85 # endif
86
87 // stdlib.h
88 int atoi(const char *nptr);
89 long atol(const char *nptr); // NOLINT
90 long strtol(const char *nptr, char **endptr, int base); // NOLINT
91 # if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
92 long long atoll(const char *nptr); // NOLINT
93 long long strtoll(const char *nptr, char **endptr, int base); // NOLINT
94 # endif
95
96 // Windows threads.
97 # if defined(_WIN32)
98 __declspec(dllimport)
99 void* __stdcall CreateThread(void *sec, size_t st, void* start,
100 void *arg, DWORD fl, DWORD *id);
101 # endif
102
103 // Posix threads.
104 # if !defined(_WIN32)
105 int pthread_create(void *thread, void *attr, void *(*start_routine)(void*),
106 void *arg);
107 # endif
108 } // extern "C"
109 #endif
110
111 namespace __asan {
112
113 // Instruments read/write access to a single byte in memory.
114 // On error calls __asan_report_error, which aborts the program.
115 #define ACCESS_ADDRESS(address, isWrite) do { \
116 if (AddressIsPoisoned(address)) { \
117 GET_CURRENT_PC_BP_SP; \
118 __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
119 } \
120 } while (0)
121
122 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
123 // and ASAN_WRITE_RANGE as macro instead of function so
124 // that no extra frames are created, and stack trace contains
125 // relevant information only.
126
127 // Instruments read/write access to a memory range.
128 // More complex implementation is possible, for now just
129 // checking the first and the last byte of a range.
130 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
131 if (size > 0) { \
132 uintptr_t ptr = (uintptr_t)(offset); \
133 ACCESS_ADDRESS(ptr, isWrite); \
134 ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
135 } \
136 } while (0)
137
138 #define ASAN_READ_RANGE(offset, size) do { \
139 ACCESS_MEMORY_RANGE(offset, size, false); \
140 } while (0)
141
142 #define ASAN_WRITE_RANGE(offset, size) do { \
143 ACCESS_MEMORY_RANGE(offset, size, true); \
144 } while (0)
145
146 // Behavior of functions like "memcpy" or "strcpy" is undefined
147 // if memory intervals overlap. We report error in this case.
148 // Macro is used to avoid creation of new frames.
RangesOverlap(const char * offset1,size_t length1,const char * offset2,size_t length2)149 static inline bool RangesOverlap(const char *offset1, size_t length1,
150 const char *offset2, size_t length2) {
151 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
152 }
153 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
154 const char *offset1 = (const char*)_offset1; \
155 const char *offset2 = (const char*)_offset2; \
156 if (RangesOverlap(offset1, length1, offset2, length2)) { \
157 Report("ERROR: AddressSanitizer %s-param-overlap: " \
158 "memory ranges [%p,%p) and [%p, %p) overlap\n", \
159 name, offset1, offset1 + length1, offset2, offset2 + length2); \
160 PRINT_CURRENT_STACK(); \
161 ShowStatsAndAbort(); \
162 } \
163 } while (0)
164
165 #define ENSURE_ASAN_INITED() do { \
166 CHECK(!asan_init_is_running); \
167 if (!asan_inited) { \
168 __asan_init(); \
169 } \
170 } while (0)
171
IsSpace(int c)172 static inline bool IsSpace(int c) {
173 return (c == ' ') || (c == '\n') || (c == '\t') ||
174 (c == '\f') || (c == '\r') || (c == '\v');
175 }
176
IsDigit(int c)177 static inline bool IsDigit(int c) {
178 return (c >= '0') && (c <= '9');
179 }
180
ToLower(int c)181 static inline int ToLower(int c) {
182 return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
183 }
184
185 // ---------------------- Internal string functions ---------------- {{{1
186
internal_simple_strtoll(const char * nptr,char ** endptr,int base)187 int64_t internal_simple_strtoll(const char *nptr, char **endptr, int base) {
188 CHECK(base == 10);
189 while (IsSpace(*nptr)) nptr++;
190 int sgn = 1;
191 uint64_t res = 0;
192 bool have_digits = false;
193 char *old_nptr = (char*)nptr;
194 if (*nptr == '+') {
195 sgn = 1;
196 nptr++;
197 } else if (*nptr == '-') {
198 sgn = -1;
199 nptr++;
200 }
201 while (IsDigit(*nptr)) {
202 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
203 int digit = ((*nptr) - '0');
204 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
205 have_digits = true;
206 nptr++;
207 }
208 if (endptr != NULL) {
209 *endptr = (have_digits) ? (char*)nptr : old_nptr;
210 }
211 if (sgn > 0) {
212 return (int64_t)(Min((uint64_t)INT64_MAX, res));
213 } else {
214 return (res > INT64_MAX) ? INT64_MIN : ((int64_t)res * -1);
215 }
216 }
217
internal_atoll(const char * nptr)218 int64_t internal_atoll(const char *nptr) {
219 return internal_simple_strtoll(nptr, (char**)NULL, 10);
220 }
221
internal_strlen(const char * s)222 size_t internal_strlen(const char *s) {
223 size_t i = 0;
224 while (s[i]) i++;
225 return i;
226 }
227
internal_strnlen(const char * s,size_t maxlen)228 size_t internal_strnlen(const char *s, size_t maxlen) {
229 #if ASAN_INTERCEPT_STRNLEN
230 if (REAL(strnlen) != NULL) {
231 return REAL(strnlen)(s, maxlen);
232 }
233 #endif
234 size_t i = 0;
235 while (i < maxlen && s[i]) i++;
236 return i;
237 }
238
internal_strchr(const char * s,int c)239 char* internal_strchr(const char *s, int c) {
240 while (true) {
241 if (*s == (char)c)
242 return (char*)s;
243 if (*s == 0)
244 return NULL;
245 s++;
246 }
247 }
248
internal_memchr(const void * s,int c,size_t n)249 void* internal_memchr(const void* s, int c, size_t n) {
250 const char* t = (char*)s;
251 for (size_t i = 0; i < n; ++i, ++t)
252 if (*t == c)
253 return (void*)t;
254 return NULL;
255 }
256
internal_memcmp(const void * s1,const void * s2,size_t n)257 int internal_memcmp(const void* s1, const void* s2, size_t n) {
258 const char* t1 = (char*)s1;
259 const char* t2 = (char*)s2;
260 for (size_t i = 0; i < n; ++i, ++t1, ++t2)
261 if (*t1 != *t2)
262 return *t1 < *t2 ? -1 : 1;
263 return 0;
264 }
265
266 // Should not be used in performance-critical places.
internal_memset(void * s,int c,size_t n)267 void* internal_memset(void* s, int c, size_t n) {
268 // The next line prevents Clang from making a call to memset() instead of the
269 // loop below.
270 // FIXME: building the runtime with -ffreestanding is a better idea. However
271 // there currently are linktime problems due to PR12396.
272 char volatile *t = (char*)s;
273 for (size_t i = 0; i < n; ++i, ++t) {
274 *t = c;
275 }
276 return s;
277 }
278
internal_strstr(const char * haystack,const char * needle)279 char *internal_strstr(const char *haystack, const char *needle) {
280 // This is O(N^2), but we are not using it in hot places.
281 size_t len1 = internal_strlen(haystack);
282 size_t len2 = internal_strlen(needle);
283 if (len1 < len2) return 0;
284 for (size_t pos = 0; pos <= len1 - len2; pos++) {
285 if (internal_memcmp(haystack + pos, needle, len2) == 0)
286 return (char*)haystack + pos;
287 }
288 return 0;
289 }
290
internal_strncat(char * dst,const char * src,size_t n)291 char *internal_strncat(char *dst, const char *src, size_t n) {
292 size_t len = internal_strlen(dst);
293 size_t i;
294 for (i = 0; i < n && src[i]; i++)
295 dst[len + i] = src[i];
296 dst[len + i] = 0;
297 return dst;
298 }
299
internal_strcmp(const char * s1,const char * s2)300 int internal_strcmp(const char *s1, const char *s2) {
301 while (true) {
302 unsigned c1 = *s1;
303 unsigned c2 = *s2;
304 if (c1 != c2) return (c1 < c2) ? -1 : 1;
305 if (c1 == 0) break;
306 s1++;
307 s2++;
308 }
309 return 0;
310 }
311
internal_strncpy(char * dst,const char * src,size_t n)312 char *internal_strncpy(char *dst, const char *src, size_t n) {
313 size_t i;
314 for (i = 0; i < n && src[i]; i++)
315 dst[i] = src[i];
316 return dst;
317 }
318
319 } // namespace __asan
320
321 // ---------------------- Wrappers ---------------- {{{1
322 using namespace __asan; // NOLINT
323
asan_thread_start(void * arg)324 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
325 AsanThread *t = (AsanThread*)arg;
326 asanThreadRegistry().SetCurrent(t);
327 return t->ThreadStart();
328 }
329
330 #ifndef _WIN32
INTERCEPTOR(int,pthread_create,void * thread,void * attr,void * (* start_routine)(void *),void * arg)331 INTERCEPTOR(int, pthread_create, void *thread,
332 void *attr, void *(*start_routine)(void*), void *arg) {
333 GET_STACK_TRACE_HERE(kStackTraceMax);
334 int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
335 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
336 asanThreadRegistry().RegisterThread(t);
337 return REAL(pthread_create)(thread, attr, asan_thread_start, t);
338 }
339 #endif // !_WIN32
340
341 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
INTERCEPTOR(void *,signal,int signum,void * handler)342 INTERCEPTOR(void*, signal, int signum, void *handler) {
343 if (!AsanInterceptsSignal(signum)) {
344 return REAL(signal)(signum, handler);
345 }
346 return NULL;
347 }
348
INTERCEPTOR(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)349 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
350 struct sigaction *oldact) {
351 if (!AsanInterceptsSignal(signum)) {
352 return REAL(sigaction)(signum, act, oldact);
353 }
354 return 0;
355 }
356 #elif ASAN_POSIX
357 // We need to have defined REAL(sigaction) on posix systems.
358 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
359 struct sigaction *oldact);
360 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
361
INTERCEPTOR(void,longjmp,void * env,int val)362 INTERCEPTOR(void, longjmp, void *env, int val) {
363 __asan_handle_no_return();
364 REAL(longjmp)(env, val);
365 }
366
367 #if !defined(_WIN32)
INTERCEPTOR(void,_longjmp,void * env,int val)368 INTERCEPTOR(void, _longjmp, void *env, int val) {
369 __asan_handle_no_return();
370 REAL(_longjmp)(env, val);
371 }
372
INTERCEPTOR(void,siglongjmp,void * env,int val)373 INTERCEPTOR(void, siglongjmp, void *env, int val) {
374 __asan_handle_no_return();
375 REAL(siglongjmp)(env, val);
376 }
377 #endif
378
379 #if ASAN_HAS_EXCEPTIONS == 1
380 #ifdef __APPLE__
381 extern "C" void __cxa_throw(void *a, void *b, void *c);
382 #endif // __APPLE__
383
INTERCEPTOR(void,__cxa_throw,void * a,void * b,void * c)384 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
385 CHECK(REAL(__cxa_throw));
386 __asan_handle_no_return();
387 REAL(__cxa_throw)(a, b, c);
388 }
389 #endif
390
391 // intercept mlock and friends.
392 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
393 // All functions return 0 (success).
MlockIsUnsupported()394 static void MlockIsUnsupported() {
395 static bool printed = 0;
396 if (printed) return;
397 printed = true;
398 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
399 }
400
401 extern "C" {
402 INTERCEPTOR_ATTRIBUTE
mlock(const void * addr,size_t len)403 int mlock(const void *addr, size_t len) {
404 MlockIsUnsupported();
405 return 0;
406 }
407
408 INTERCEPTOR_ATTRIBUTE
munlock(const void * addr,size_t len)409 int munlock(const void *addr, size_t len) {
410 MlockIsUnsupported();
411 return 0;
412 }
413
414 INTERCEPTOR_ATTRIBUTE
mlockall(int flags)415 int mlockall(int flags) {
416 MlockIsUnsupported();
417 return 0;
418 }
419
420 INTERCEPTOR_ATTRIBUTE
munlockall(void)421 int munlockall(void) {
422 MlockIsUnsupported();
423 return 0;
424 }
425 } // extern "C"
426
CharCmp(unsigned char c1,unsigned char c2)427 static inline int CharCmp(unsigned char c1, unsigned char c2) {
428 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
429 }
430
CharCaseCmp(unsigned char c1,unsigned char c2)431 static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
432 int c1_low = ToLower(c1);
433 int c2_low = ToLower(c2);
434 return c1_low - c2_low;
435 }
436
INTERCEPTOR(int,memcmp,const void * a1,const void * a2,size_t size)437 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, size_t size) {
438 ENSURE_ASAN_INITED();
439 unsigned char c1 = 0, c2 = 0;
440 const unsigned char *s1 = (const unsigned char*)a1;
441 const unsigned char *s2 = (const unsigned char*)a2;
442 size_t i;
443 for (i = 0; i < size; i++) {
444 c1 = s1[i];
445 c2 = s2[i];
446 if (c1 != c2) break;
447 }
448 ASAN_READ_RANGE(s1, Min(i + 1, size));
449 ASAN_READ_RANGE(s2, Min(i + 1, size));
450 return CharCmp(c1, c2);
451 }
452
INTERCEPTOR(void *,memcpy,void * to,const void * from,size_t size)453 INTERCEPTOR(void*, memcpy, void *to, const void *from, size_t size) {
454 // memcpy is called during __asan_init() from the internals
455 // of printf(...).
456 if (asan_init_is_running) {
457 return REAL(memcpy)(to, from, size);
458 }
459 ENSURE_ASAN_INITED();
460 if (FLAG_replace_intrin) {
461 if (to != from) {
462 // We do not treat memcpy with to==from as a bug.
463 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
464 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
465 }
466 ASAN_WRITE_RANGE(from, size);
467 ASAN_READ_RANGE(to, size);
468 }
469 return REAL(memcpy)(to, from, size);
470 }
471
INTERCEPTOR(void *,memmove,void * to,const void * from,size_t size)472 INTERCEPTOR(void*, memmove, void *to, const void *from, size_t size) {
473 ENSURE_ASAN_INITED();
474 if (FLAG_replace_intrin) {
475 ASAN_WRITE_RANGE(from, size);
476 ASAN_READ_RANGE(to, size);
477 }
478 return REAL(memmove)(to, from, size);
479 }
480
INTERCEPTOR(void *,memset,void * block,int c,size_t size)481 INTERCEPTOR(void*, memset, void *block, int c, size_t size) {
482 // memset is called inside Printf.
483 if (asan_init_is_running) {
484 return REAL(memset)(block, c, size);
485 }
486 ENSURE_ASAN_INITED();
487 if (FLAG_replace_intrin) {
488 ASAN_WRITE_RANGE(block, size);
489 }
490 return REAL(memset)(block, c, size);
491 }
492
INTERCEPTOR(char *,strchr,const char * str,int c)493 INTERCEPTOR(char*, strchr, const char *str, int c) {
494 ENSURE_ASAN_INITED();
495 char *result = REAL(strchr)(str, c);
496 if (FLAG_replace_str) {
497 size_t bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
498 ASAN_READ_RANGE(str, bytes_read);
499 }
500 return result;
501 }
502
503 #ifdef __linux__
504 INTERCEPTOR(char*, index, const char *string, int c)
505 ALIAS(WRAPPER_NAME(strchr));
506 #else
507 DEFINE_REAL(char*, index, const char *string, int c);
508 #endif
509
INTERCEPTOR(int,strcasecmp,const char * s1,const char * s2)510 INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
511 ENSURE_ASAN_INITED();
512 unsigned char c1, c2;
513 size_t i;
514 for (i = 0; ; i++) {
515 c1 = (unsigned char)s1[i];
516 c2 = (unsigned char)s2[i];
517 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
518 }
519 ASAN_READ_RANGE(s1, i + 1);
520 ASAN_READ_RANGE(s2, i + 1);
521 return CharCaseCmp(c1, c2);
522 }
523
INTERCEPTOR(char *,strcat,char * to,const char * from)524 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
525 ENSURE_ASAN_INITED();
526 if (FLAG_replace_str) {
527 size_t from_length = REAL(strlen)(from);
528 ASAN_READ_RANGE(from, from_length + 1);
529 if (from_length > 0) {
530 size_t to_length = REAL(strlen)(to);
531 ASAN_READ_RANGE(to, to_length);
532 ASAN_WRITE_RANGE(to + to_length, from_length + 1);
533 CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1);
534 }
535 }
536 return REAL(strcat)(to, from); // NOLINT
537 }
538
INTERCEPTOR(int,strcmp,const char * s1,const char * s2)539 INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
540 if (!asan_inited) {
541 return internal_strcmp(s1, s2);
542 }
543 unsigned char c1, c2;
544 size_t i;
545 for (i = 0; ; i++) {
546 c1 = (unsigned char)s1[i];
547 c2 = (unsigned char)s2[i];
548 if (c1 != c2 || c1 == '\0') break;
549 }
550 ASAN_READ_RANGE(s1, i + 1);
551 ASAN_READ_RANGE(s2, i + 1);
552 return CharCmp(c1, c2);
553 }
554
INTERCEPTOR(char *,strcpy,char * to,const char * from)555 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
556 // strcpy is called from malloc_default_purgeable_zone()
557 // in __asan::ReplaceSystemAlloc() on Mac.
558 if (asan_init_is_running) {
559 return REAL(strcpy)(to, from); // NOLINT
560 }
561 ENSURE_ASAN_INITED();
562 if (FLAG_replace_str) {
563 size_t from_size = REAL(strlen)(from) + 1;
564 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
565 ASAN_READ_RANGE(from, from_size);
566 ASAN_WRITE_RANGE(to, from_size);
567 }
568 return REAL(strcpy)(to, from); // NOLINT
569 }
570
INTERCEPTOR(char *,strdup,const char * s)571 INTERCEPTOR(char*, strdup, const char *s) {
572 ENSURE_ASAN_INITED();
573 if (FLAG_replace_str) {
574 size_t length = REAL(strlen)(s);
575 ASAN_READ_RANGE(s, length + 1);
576 }
577 return REAL(strdup)(s);
578 }
579
INTERCEPTOR(size_t,strlen,const char * s)580 INTERCEPTOR(size_t, strlen, const char *s) {
581 // strlen is called from malloc_default_purgeable_zone()
582 // in __asan::ReplaceSystemAlloc() on Mac.
583 if (asan_init_is_running) {
584 return REAL(strlen)(s);
585 }
586 ENSURE_ASAN_INITED();
587 size_t length = REAL(strlen)(s);
588 if (FLAG_replace_str) {
589 ASAN_READ_RANGE(s, length + 1);
590 }
591 return length;
592 }
593
INTERCEPTOR(int,strncasecmp,const char * s1,const char * s2,size_t n)594 INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, size_t n) {
595 ENSURE_ASAN_INITED();
596 unsigned char c1 = 0, c2 = 0;
597 size_t i;
598 for (i = 0; i < n; i++) {
599 c1 = (unsigned char)s1[i];
600 c2 = (unsigned char)s2[i];
601 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
602 }
603 ASAN_READ_RANGE(s1, Min(i + 1, n));
604 ASAN_READ_RANGE(s2, Min(i + 1, n));
605 return CharCaseCmp(c1, c2);
606 }
607
INTERCEPTOR(int,strncmp,const char * s1,const char * s2,size_t size)608 INTERCEPTOR(int, strncmp, const char *s1, const char *s2, size_t size) {
609 // strncmp is called from malloc_default_purgeable_zone()
610 // in __asan::ReplaceSystemAlloc() on Mac.
611 if (asan_init_is_running) {
612 return REAL(strncmp)(s1, s2, size);
613 }
614 unsigned char c1 = 0, c2 = 0;
615 size_t i;
616 for (i = 0; i < size; i++) {
617 c1 = (unsigned char)s1[i];
618 c2 = (unsigned char)s2[i];
619 if (c1 != c2 || c1 == '\0') break;
620 }
621 ASAN_READ_RANGE(s1, Min(i + 1, size));
622 ASAN_READ_RANGE(s2, Min(i + 1, size));
623 return CharCmp(c1, c2);
624 }
625
INTERCEPTOR(char *,strncpy,char * to,const char * from,size_t size)626 INTERCEPTOR(char*, strncpy, char *to, const char *from, size_t size) {
627 ENSURE_ASAN_INITED();
628 if (FLAG_replace_str) {
629 size_t from_size = Min(size, internal_strnlen(from, size) + 1);
630 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
631 ASAN_READ_RANGE(from, from_size);
632 ASAN_WRITE_RANGE(to, size);
633 }
634 return REAL(strncpy)(to, from, size);
635 }
636
637 #if ASAN_INTERCEPT_STRNLEN
INTERCEPTOR(size_t,strnlen,const char * s,size_t maxlen)638 INTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
639 ENSURE_ASAN_INITED();
640 size_t length = REAL(strnlen)(s, maxlen);
641 if (FLAG_replace_str) {
642 ASAN_READ_RANGE(s, Min(length + 1, maxlen));
643 }
644 return length;
645 }
646 #endif // ASAN_INTERCEPT_STRNLEN
647
IsValidStrtolBase(int base)648 static inline bool IsValidStrtolBase(int base) {
649 return (base == 0) || (2 <= base && base <= 36);
650 }
651
FixRealStrtolEndptr(const char * nptr,char ** endptr)652 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
653 CHECK(endptr != NULL);
654 if (nptr == *endptr) {
655 // No digits were found at strtol call, we need to find out the last
656 // symbol accessed by strtoll on our own.
657 // We get this symbol by skipping leading blanks and optional +/- sign.
658 while (IsSpace(*nptr)) nptr++;
659 if (*nptr == '+' || *nptr == '-') nptr++;
660 *endptr = (char*)nptr;
661 }
662 CHECK(*endptr >= nptr);
663 }
664
INTERCEPTOR(long,strtol,const char * nptr,char ** endptr,int base)665 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
666 char **endptr, int base) {
667 ENSURE_ASAN_INITED();
668 if (!FLAG_replace_str) {
669 return REAL(strtol)(nptr, endptr, base);
670 }
671 char *real_endptr;
672 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
673 if (endptr != NULL) {
674 *endptr = real_endptr;
675 }
676 if (IsValidStrtolBase(base)) {
677 FixRealStrtolEndptr(nptr, &real_endptr);
678 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
679 }
680 return result;
681 }
682
INTERCEPTOR(int,atoi,const char * nptr)683 INTERCEPTOR(int, atoi, const char *nptr) {
684 ENSURE_ASAN_INITED();
685 if (!FLAG_replace_str) {
686 return REAL(atoi)(nptr);
687 }
688 char *real_endptr;
689 // "man atoi" tells that behavior of atoi(nptr) is the same as
690 // strtol(nptr, NULL, 10), i.e. it sets errno to ERANGE if the
691 // parsed integer can't be stored in *long* type (even if it's
692 // different from int). So, we just imitate this behavior.
693 int result = REAL(strtol)(nptr, &real_endptr, 10);
694 FixRealStrtolEndptr(nptr, &real_endptr);
695 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
696 return result;
697 }
698
INTERCEPTOR(long,atol,const char * nptr)699 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
700 ENSURE_ASAN_INITED();
701 if (!FLAG_replace_str) {
702 return REAL(atol)(nptr);
703 }
704 char *real_endptr;
705 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
706 FixRealStrtolEndptr(nptr, &real_endptr);
707 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
708 return result;
709 }
710
711 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long,strtoll,const char * nptr,char ** endptr,int base)712 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
713 char **endptr, int base) {
714 ENSURE_ASAN_INITED();
715 if (!FLAG_replace_str) {
716 return REAL(strtoll)(nptr, endptr, base);
717 }
718 char *real_endptr;
719 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
720 if (endptr != NULL) {
721 *endptr = real_endptr;
722 }
723 // If base has unsupported value, strtoll can exit with EINVAL
724 // without reading any characters. So do additional checks only
725 // if base is valid.
726 if (IsValidStrtolBase(base)) {
727 FixRealStrtolEndptr(nptr, &real_endptr);
728 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
729 }
730 return result;
731 }
732
INTERCEPTOR(long long,atoll,const char * nptr)733 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
734 ENSURE_ASAN_INITED();
735 if (!FLAG_replace_str) {
736 return REAL(atoll)(nptr);
737 }
738 char *real_endptr;
739 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
740 FixRealStrtolEndptr(nptr, &real_endptr);
741 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
742 return result;
743 }
744 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
745
746 #if defined(_WIN32)
INTERCEPTOR_WINAPI(DWORD,CreateThread,void * security,size_t stack_size,DWORD (__stdcall * start_routine)(void *),void * arg,DWORD flags,void * tid)747 INTERCEPTOR_WINAPI(DWORD, CreateThread,
748 void* security, size_t stack_size,
749 DWORD (__stdcall *start_routine)(void*), void* arg,
750 DWORD flags, void* tid) {
751 GET_STACK_TRACE_HERE(kStackTraceMax);
752 int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
753 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
754 asanThreadRegistry().RegisterThread(t);
755 return REAL(CreateThread)(security, stack_size,
756 asan_thread_start, t, flags, tid);
757 }
758
759 namespace __asan {
InitializeWindowsInterceptors()760 void InitializeWindowsInterceptors() {
761 CHECK(INTERCEPT_FUNCTION(CreateThread));
762 }
763
764 } // namespace __asan
765 #endif
766
767 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
768 namespace __asan {
InitializeAsanInterceptors()769 void InitializeAsanInterceptors() {
770 static bool was_called_once;
771 CHECK(was_called_once == false);
772 was_called_once = true;
773 // Intercept mem* functions.
774 CHECK(INTERCEPT_FUNCTION(memcmp));
775 CHECK(INTERCEPT_FUNCTION(memmove));
776 CHECK(INTERCEPT_FUNCTION(memset));
777 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
778 CHECK(INTERCEPT_FUNCTION(memcpy));
779 } else {
780 REAL(memcpy) = REAL(memmove);
781 }
782
783 // Intercept str* functions.
784 CHECK(INTERCEPT_FUNCTION(strcat)); // NOLINT
785 CHECK(INTERCEPT_FUNCTION(strchr));
786 CHECK(INTERCEPT_FUNCTION(strcmp));
787 CHECK(INTERCEPT_FUNCTION(strcpy)); // NOLINT
788 CHECK(INTERCEPT_FUNCTION(strlen));
789 CHECK(INTERCEPT_FUNCTION(strncmp));
790 CHECK(INTERCEPT_FUNCTION(strncpy));
791 #if !defined(_WIN32)
792 CHECK(INTERCEPT_FUNCTION(strcasecmp));
793 CHECK(INTERCEPT_FUNCTION(strdup));
794 CHECK(INTERCEPT_FUNCTION(strncasecmp));
795 # ifndef __APPLE__
796 CHECK(INTERCEPT_FUNCTION(index));
797 # else
798 CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
799 # endif
800 #endif
801 #if ASAN_INTERCEPT_STRNLEN
802 CHECK(INTERCEPT_FUNCTION(strnlen));
803 #endif
804
805 CHECK(INTERCEPT_FUNCTION(atoi));
806 CHECK(INTERCEPT_FUNCTION(atol));
807 CHECK(INTERCEPT_FUNCTION(strtol));
808 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
809 CHECK(INTERCEPT_FUNCTION(atoll));
810 CHECK(INTERCEPT_FUNCTION(strtoll));
811 #endif
812
813 // Intecept signal- and jump-related functions.
814 CHECK(INTERCEPT_FUNCTION(longjmp));
815 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
816 CHECK(INTERCEPT_FUNCTION(sigaction));
817 CHECK(INTERCEPT_FUNCTION(signal));
818 #endif
819
820 #if !defined(_WIN32)
821 CHECK(INTERCEPT_FUNCTION(_longjmp));
822 INTERCEPT_FUNCTION(__cxa_throw);
823 # if !defined(__APPLE__)
824 // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
825 // there.
826 CHECK(INTERCEPT_FUNCTION(siglongjmp));
827 # endif
828 #endif
829
830 // Intercept threading-related functions
831 #if !defined(_WIN32)
832 CHECK(INTERCEPT_FUNCTION(pthread_create));
833 #endif
834
835 // Some Windows-specific interceptors.
836 #if defined(_WIN32)
837 InitializeWindowsInterceptors();
838 #endif
839
840 // Some Mac-specific interceptors.
841 #if defined(__APPLE__)
842 InitializeMacInterceptors();
843 #endif
844
845 if (FLAG_v > 0) {
846 Report("AddressSanitizer: libc interceptors initialized\n");
847 }
848 }
849
850 } // namespace __asan
851