• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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