blob: 462920413d4e0ece2314a7343ad9e9ba964db60b [file] [log] [blame]
Evgeniy Stepanovc5033782012-12-11 12:27:27 +00001//===-- msan_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 MemorySanitizer.
11//
12// Interceptors for standard library functions.
Kostya Serebryany9a58d392012-12-12 09:54:35 +000013//
14// FIXME: move as many interceptors as possible into
15// sanitizer_common/sanitizer_common_interceptors.h
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000016//===----------------------------------------------------------------------===//
17
18#include "interception/interception.h"
19#include "msan.h"
20#include "msan_platform_limits_posix.h"
21#include "sanitizer_common/sanitizer_common.h"
22#include "sanitizer_common/sanitizer_libc.h"
23
24#include <stdarg.h>
25// ACHTUNG! No other system header includes in this file.
26// Ideally, we should get rid of stdarg.h as well.
27
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000028using namespace __msan;
29
30#define ENSURE_MSAN_INITED() do { \
Alexey Samsonovcd1e68e2012-12-14 11:52:02 +000031 CHECK(!msan_init_is_running); \
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000032 if (!msan_inited) { \
33 __msan_init(); \
34 } \
35} while (0)
36
37#define CHECK_UNPOISONED(x, n) \
38 do { \
39 sptr offset = __msan_test_shadow(x, n); \
40 if (offset >= 0 && flags()->report_umrs) { \
41 GET_CALLER_PC_BP_SP; \
42 (void)sp; \
43 Printf("UMR in %s at offset %d inside [%p, +%d) \n", \
44 __FUNCTION__, offset, x, n); \
45 __msan::PrintWarningWithOrigin( \
46 pc, bp, __msan_get_origin((char*)x + offset)); \
47 } \
48 } while (0)
49
Kostya Serebryany07bb3922012-12-13 06:31:40 +000050static void *fast_memset(void *ptr, int c, SIZE_T n);
51static void *fast_memcpy(void *dst, const void *src, SIZE_T n);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000052
Kostya Serebryany07bb3922012-12-13 06:31:40 +000053INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000054 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +000055 SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000056 if (res > 0)
57 __msan_unpoison(ptr, res *size);
58 return res;
59}
60
Kostya Serebryany07bb3922012-12-13 06:31:40 +000061INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000062 void *file) {
63 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +000064 SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000065 if (res > 0)
66 __msan_unpoison(ptr, res *size);
67 return res;
68}
69
Kostya Serebryany07bb3922012-12-13 06:31:40 +000070INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000071 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +000072 SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000073 if (res > 0)
74 __msan_unpoison(buf, res);
75 return res;
76}
77
78INTERCEPTOR(void *, readdir, void *a) {
79 ENSURE_MSAN_INITED();
80 void *res = REAL(readdir)(a);
81 __msan_unpoison(res, __msan::struct_dirent_sz);
82 return res;
83}
84
Kostya Serebryany07bb3922012-12-13 06:31:40 +000085INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000086 return __msan_memcpy(dest, src, n);
87}
88
Kostya Serebryany07bb3922012-12-13 06:31:40 +000089INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000090 return __msan_memmove(dest, src, n);
91}
92
Kostya Serebryany07bb3922012-12-13 06:31:40 +000093INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000094 return __msan_memset(s, c, n);
95}
96
Kostya Serebryany07bb3922012-12-13 06:31:40 +000097INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +000098 GET_MALLOC_STACK_TRACE;
99 CHECK_EQ(alignment & (alignment - 1), 0);
100 *memptr = MsanReallocate(&stack, 0, size, alignment, false);
101 CHECK_NE(memptr, 0);
102 return 0;
103}
104
105INTERCEPTOR(void, free, void *ptr) {
106 ENSURE_MSAN_INITED();
107 if (ptr == 0) return;
108 MsanDeallocate(ptr);
109}
110
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000111INTERCEPTOR(SIZE_T, strlen, const char *s) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000112 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000113 SIZE_T res = REAL(strlen)(s);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000114 CHECK_UNPOISONED(s, res + 1);
115 return res;
116}
117
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000118INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000119 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000120 SIZE_T res = REAL(strnlen)(s, n);
121 SIZE_T scan_size = (res == n) ? res : res + 1;
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000122 CHECK_UNPOISONED(s, scan_size);
123 return res;
124}
125
126// FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should
127// check the shadow of the terminating \0 byte).
128
129INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT
130 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000131 SIZE_T n = REAL(strlen)(src);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000132 char *res = REAL(strcpy)(dest, src); // NOLINT
133 __msan_copy_poison(dest, src, n + 1);
134 return res;
135}
136
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000137INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000138 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000139 SIZE_T copy_size = REAL(strnlen)(src, n);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000140 if (copy_size < n)
141 copy_size++; // trailing \0
142 char *res = REAL(strncpy)(dest, src, n); // NOLINT
143 __msan_copy_poison(dest, src, copy_size);
144 return res;
145}
146
147INTERCEPTOR(char *, strdup, char *src) {
148 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000149 SIZE_T n = REAL(strlen)(src);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000150 char *res = REAL(strdup)(src);
151 __msan_copy_poison(res, src, n + 1);
152 return res;
153}
154
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000155INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000156 ENSURE_MSAN_INITED();
157 char *res = REAL(gcvt)(number, ndigit, buf);
158 // DynamoRio tool will take care of unpoisoning gcvt result for us.
159 if (!__msan_has_dynamic_component()) {
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000160 SIZE_T n = REAL(strlen)(buf);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000161 __msan_unpoison(buf, n + 1);
162 }
163 return res;
164}
165
166INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT
167 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000168 SIZE_T src_size = REAL(strlen)(src);
169 SIZE_T dest_size = REAL(strlen)(dest);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000170 char *res = REAL(strcat)(dest, src); // NOLINT
171 __msan_copy_poison(dest + dest_size, src, src_size + 1);
172 return res;
173}
174
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000175INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000176 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000177 SIZE_T dest_size = REAL(strlen)(dest);
178 SIZE_T copy_size = REAL(strlen)(src);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000179 if (copy_size < n)
180 copy_size++; // trailing \0
181 char *res = REAL(strncat)(dest, src, n); // NOLINT
182 __msan_copy_poison(dest + dest_size, src, copy_size);
183 return res;
184}
185
186INTERCEPTOR(long, strtol, const char *nptr, char **endptr, // NOLINT
187 int base) {
188 ENSURE_MSAN_INITED();
189 long res = REAL(strtol)(nptr, endptr, base); // NOLINT
190 if (!__msan_has_dynamic_component()) {
191 __msan_unpoison(endptr, sizeof(*endptr));
192 }
193 return res;
194}
195
196INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, // NOLINT
197 int base) {
198 ENSURE_MSAN_INITED();
199 long res = REAL(strtoll)(nptr, endptr, base); //NOLINT
200 if (!__msan_has_dynamic_component()) {
201 __msan_unpoison(endptr, sizeof(*endptr));
202 }
203 return res;
204}
205
206INTERCEPTOR(unsigned long, strtoul, const char *nptr, char **endptr, // NOLINT
207 int base) {
208 ENSURE_MSAN_INITED();
209 unsigned long res = REAL(strtoul)(nptr, endptr, base); // NOLINT
210 if (!__msan_has_dynamic_component()) {
211 __msan_unpoison(endptr, sizeof(*endptr));
212 }
213 return res;
214}
215
216INTERCEPTOR(unsigned long long, strtoull, const char *nptr, // NOLINT
217 char **endptr, int base) {
218 ENSURE_MSAN_INITED();
219 unsigned long res = REAL(strtoull)(nptr, endptr, base); // NOLINT
220 if (!__msan_has_dynamic_component()) {
221 __msan_unpoison(endptr, sizeof(*endptr));
222 }
223 return res;
224}
225
Evgeniy Stepanove3a32512013-01-17 13:42:17 +0000226INTERCEPTOR(double, strtod, const char *nptr, char **endptr) { // NOLINT
227 ENSURE_MSAN_INITED();
228 double res = REAL(strtod)(nptr, endptr); // NOLINT
229 if (!__msan_has_dynamic_component()) {
230 __msan_unpoison(endptr, sizeof(*endptr));
231 }
232 return res;
233}
234
235INTERCEPTOR(float, strtof, const char *nptr, char **endptr) { // NOLINT
236 ENSURE_MSAN_INITED();
237 float res = REAL(strtof)(nptr, endptr); // NOLINT
238 if (!__msan_has_dynamic_component()) {
239 __msan_unpoison(endptr, sizeof(*endptr));
240 }
241 return res;
242}
243
244INTERCEPTOR(long double, strtold, const char *nptr, char **endptr) { // NOLINT
245 ENSURE_MSAN_INITED();
246 long double res = REAL(strtold)(nptr, endptr); // NOLINT
247 if (!__msan_has_dynamic_component()) {
248 __msan_unpoison(endptr, sizeof(*endptr));
249 }
250 return res;
251}
252
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000253INTERCEPTOR(int, vsnprintf, char *str, uptr size,
254 const char *format, va_list ap) {
255 ENSURE_MSAN_INITED();
256 int res = REAL(vsnprintf)(str, size, format, ap);
257 if (!__msan_has_dynamic_component()) {
258 __msan_unpoison(str, res + 1);
259 }
260 return res;
261}
262
263INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) {
264 ENSURE_MSAN_INITED();
265 int res = REAL(vsprintf)(str, format, ap);
266 if (!__msan_has_dynamic_component()) {
267 __msan_unpoison(str, res + 1);
268 }
269 return res;
270}
271
272INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
273 ENSURE_MSAN_INITED();
274 int res = REAL(vswprintf)(str, size, format, ap);
275 if (!__msan_has_dynamic_component()) {
276 __msan_unpoison(str, 4 * (res + 1));
277 }
278 return res;
279}
280
281INTERCEPTOR(int, sprintf, char *str, const char *format, ...) { // NOLINT
282 ENSURE_MSAN_INITED();
283 va_list ap;
284 va_start(ap, format);
285 int res = vsprintf(str, format, ap); // NOLINT
286 va_end(ap);
287 return res;
288}
289
290INTERCEPTOR(int, snprintf, char *str, uptr size, const char *format, ...) {
291 ENSURE_MSAN_INITED();
292 va_list ap;
293 va_start(ap, format);
294 int res = vsnprintf(str, size, format, ap);
295 va_end(ap);
296 return res;
297}
298
299INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
300 ENSURE_MSAN_INITED();
301 va_list ap;
302 va_start(ap, format);
303 int res = vswprintf(str, size, format, ap);
304 va_end(ap);
305 return res;
306}
307
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000308// SIZE_T strftime(char *s, SIZE_T max, const char *format,const struct tm *tm);
309INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000310 void *tm) {
311 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000312 SIZE_T res = REAL(strftime)(s, max, format, tm);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000313 if (res) __msan_unpoison(s, res + 1);
314 return res;
315}
316
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000317INTERCEPTOR(SIZE_T, wcstombs, void *dest, void *src, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000318 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000319 SIZE_T res = REAL(wcstombs)(dest, src, size);
320 if (res != (SIZE_T)-1) __msan_unpoison(dest, res + 1);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000321 return res;
322}
323
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000324// SIZE_T mbstowcs(wchar_t *dest, const char *src, SIZE_T n);
325INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000326 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000327 SIZE_T res = REAL(mbstowcs)(dest, src, n);
328 if (res != (SIZE_T)-1) __msan_unpoison(dest, (res + 1) * sizeof(wchar_t));
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000329 return res;
330}
331
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000332INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000333 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000334 SIZE_T res = REAL(wcslen)(s);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000335 CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
336 return res;
337}
338
339// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
340INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
341 ENSURE_MSAN_INITED();
342 wchar_t *res = REAL(wcschr)(s, wc, ps);
343 return res;
344}
345
346// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
347INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
348 ENSURE_MSAN_INITED();
349 wchar_t *res = REAL(wcscpy)(dest, src);
350 __msan_copy_poison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1));
351 return res;
352}
353
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000354// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
355INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000356 ENSURE_MSAN_INITED();
357 wchar_t *res = REAL(wmemcpy)(dest, src, n);
358 __msan_copy_poison(dest, src, n * sizeof(wchar_t));
359 return res;
360}
361
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000362INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000363 CHECK(MEM_IS_APP(s));
364 ENSURE_MSAN_INITED();
365 wchar_t *res = (wchar_t *)fast_memset(s, c, n * sizeof(wchar_t));
366 __msan_unpoison(s, n * sizeof(wchar_t));
367 return res;
368}
369
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000370INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000371 ENSURE_MSAN_INITED();
372 wchar_t *res = REAL(wmemmove)(dest, src, n);
373 __msan_move_poison(dest, src, n * sizeof(wchar_t));
374 return res;
375}
376
377INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
378 ENSURE_MSAN_INITED();
379 int res = REAL(wcscmp)(s1, s2);
380 return res;
381}
382
383INTERCEPTOR(double, wcstod, const wchar_t *nptr, wchar_t **endptr) {
384 ENSURE_MSAN_INITED();
385 double res = REAL(wcstod)(nptr, endptr);
386 __msan_unpoison(endptr, sizeof(*endptr));
387 return res;
388}
389
390// #define UNSUPPORTED(name) \
391// INTERCEPTOR(void, name, void) { \
392// Printf("MSAN: Unsupported %s\n", __FUNCTION__); \
393// Die(); \
394// }
395
396// FIXME: intercept the following functions:
397// Note, they only matter when running without a dynamic tool.
398// UNSUPPORTED(wcscoll_l)
399// UNSUPPORTED(wcsnrtombs)
400// UNSUPPORTED(wcstol)
401// UNSUPPORTED(wcstoll)
402// UNSUPPORTED(wcstold)
403// UNSUPPORTED(wcstoul)
404// UNSUPPORTED(wcstoull)
405// UNSUPPORTED(wcsxfrm_l)
406// UNSUPPORTED(wcsdup)
407// UNSUPPORTED(wcsftime)
408// UNSUPPORTED(wcsstr)
409// UNSUPPORTED(wcsrchr)
410// UNSUPPORTED(wctob)
411
412INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
413 ENSURE_MSAN_INITED();
414 int res = REAL(gettimeofday)(tv, tz);
415 if (tv)
416 __msan_unpoison(tv, 16);
417 if (tz)
418 __msan_unpoison(tz, 8);
419 return res;
420}
421
422INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
423 ENSURE_MSAN_INITED();
424 char *res = REAL(fcvt)(x, a, b, c);
425 if (!__msan_has_dynamic_component()) {
426 __msan_unpoison(b, sizeof(*b));
427 __msan_unpoison(c, sizeof(*c));
428 }
429 return res;
430}
431
432INTERCEPTOR(char *, getenv, char *name) {
433 ENSURE_MSAN_INITED();
434 char *res = REAL(getenv)(name);
435 if (!__msan_has_dynamic_component()) {
436 if (res)
437 __msan_unpoison(res, REAL(strlen)(res) + 1);
438 }
439 return res;
440}
441
442INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
443 ENSURE_MSAN_INITED();
444 int res = REAL(__fxstat)(magic, fd, buf);
445 if (!res)
446 __msan_unpoison(buf, __msan::struct_stat_sz);
447 return res;
448}
449
450INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
451 ENSURE_MSAN_INITED();
452 int res = REAL(__fxstat64)(magic, fd, buf);
453 if (!res)
454 __msan_unpoison(buf, __msan::struct_stat64_sz);
455 return res;
456}
457
458INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
459 ENSURE_MSAN_INITED();
460 int res = REAL(__xstat)(magic, path, buf);
461 if (!res)
462 __msan_unpoison(buf, __msan::struct_stat_sz);
463 return res;
464}
465
466INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) {
467 ENSURE_MSAN_INITED();
468 int res = REAL(__xstat64)(magic, path, buf);
469 if (!res)
470 __msan_unpoison(buf, __msan::struct_stat64_sz);
471 return res;
472}
473
474INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) {
475 ENSURE_MSAN_INITED();
476 int res = REAL(__lxstat)(magic, path, buf);
477 if (!res)
478 __msan_unpoison(buf, __msan::struct_stat_sz);
479 return res;
480}
481
482INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) {
483 ENSURE_MSAN_INITED();
484 int res = REAL(__lxstat64)(magic, path, buf);
485 if (!res)
486 __msan_unpoison(buf, __msan::struct_stat64_sz);
487 return res;
488}
489
490INTERCEPTOR(int, pipe, int pipefd[2]) {
491 if (msan_init_is_running)
492 return REAL(pipe)(pipefd);
493 ENSURE_MSAN_INITED();
494 int res = REAL(pipe)(pipefd);
495 if (!res)
496 __msan_unpoison(pipefd, sizeof(int[2]));
497 return res;
498}
499
500INTERCEPTOR(int, wait, int *status) {
501 ENSURE_MSAN_INITED();
502 int res = REAL(wait)(status);
503 if (status)
504 __msan_unpoison(status, sizeof(*status));
505 return res;
506}
507
508INTERCEPTOR(int, waitpid, int pid, int *status, int options) {
509 ENSURE_MSAN_INITED();
510 int res = REAL(waitpid)(pid, status, options);
511 if (status)
512 __msan_unpoison(status, sizeof(*status));
513 return res;
514}
515
516INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
517 ENSURE_MSAN_INITED();
518 char *res = REAL(fgets)(s, size, stream);
519 if (res)
520 __msan_unpoison(s, REAL(strlen)(s) + 1);
521 return res;
522}
523
524INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
525 ENSURE_MSAN_INITED();
526 char *res = REAL(fgets_unlocked)(s, size, stream);
527 if (res)
528 __msan_unpoison(s, REAL(strlen)(s) + 1);
529 return res;
530}
531
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000532INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000533 ENSURE_MSAN_INITED();
534 char *res = REAL(getcwd)(buf, size);
535 if (res)
536 __msan_unpoison(buf, REAL(strlen)(buf) + 1);
537 return res;
538}
539
540INTERCEPTOR(char *, realpath, char *path, char *abspath) {
541 ENSURE_MSAN_INITED();
542 char *res = REAL(realpath)(path, abspath);
543 if (res)
544 __msan_unpoison(abspath, REAL(strlen)(abspath) + 1);
545 return res;
546}
547
548INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
549 if (msan_init_is_running)
550 return REAL(getrlimit)(resource, rlim);
551 ENSURE_MSAN_INITED();
552 int res = REAL(getrlimit)(resource, rlim);
553 if (!res)
554 __msan_unpoison(rlim, __msan::struct_rlimit_sz);
555 return res;
556}
557
558INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
559 if (msan_init_is_running)
560 return REAL(getrlimit64)(resource, rlim);
561 ENSURE_MSAN_INITED();
562 int res = REAL(getrlimit64)(resource, rlim);
563 if (!res)
564 __msan_unpoison(rlim, __msan::struct_rlimit64_sz);
565 return res;
566}
567
568INTERCEPTOR(int, statfs, const char *s, void *buf) {
569 ENSURE_MSAN_INITED();
570 int res = REAL(statfs)(s, buf);
571 if (!res)
572 __msan_unpoison(buf, __msan::struct_statfs_sz);
573 return res;
574}
575
576INTERCEPTOR(int, fstatfs, int fd, void *buf) {
577 ENSURE_MSAN_INITED();
578 int res = REAL(fstatfs)(fd, buf);
579 if (!res)
580 __msan_unpoison(buf, __msan::struct_statfs_sz);
581 return res;
582}
583
584INTERCEPTOR(int, statfs64, const char *s, void *buf) {
585 ENSURE_MSAN_INITED();
586 int res = REAL(statfs64)(s, buf);
587 if (!res)
588 __msan_unpoison(buf, __msan::struct_statfs64_sz);
589 return res;
590}
591
592INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
593 ENSURE_MSAN_INITED();
594 int res = REAL(fstatfs64)(fd, buf);
595 if (!res)
596 __msan_unpoison(buf, __msan::struct_statfs64_sz);
597 return res;
598}
599
600INTERCEPTOR(int, uname, void *utsname) {
601 ENSURE_MSAN_INITED();
602 int res = REAL(uname)(utsname);
603 if (!res) {
604 __msan_unpoison(utsname, __msan::struct_utsname_sz);
605 }
606 return res;
607}
608
609INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
610 int timeout) {
611 ENSURE_MSAN_INITED();
612 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
613 if (res > 0) {
614 __msan_unpoison(events, __msan::struct_epoll_event_sz * res);
615 }
616 return res;
617}
618
619INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
620 int timeout, void *sigmask) {
621 ENSURE_MSAN_INITED();
622 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
623 if (res > 0) {
624 __msan_unpoison(events, __msan::struct_epoll_event_sz * res);
625 }
626 return res;
627}
628
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000629INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000630 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000631 SSIZE_T res = REAL(recv)(fd, buf, len, flags);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000632 if (res > 0)
633 __msan_unpoison(buf, res);
634 return res;
635}
636
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000637INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000638 void *srcaddr, void *addrlen) {
639 ENSURE_MSAN_INITED();
Evgeniy Stepanov84f46d92012-12-25 16:51:57 +0000640 SIZE_T srcaddr_sz;
641 if (srcaddr)
642 srcaddr_sz = __msan_get_socklen_t(addrlen);
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000643 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
Evgeniy Stepanov84f46d92012-12-25 16:51:57 +0000644 if (res > 0) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000645 __msan_unpoison(buf, res);
Evgeniy Stepanov84f46d92012-12-25 16:51:57 +0000646 if (srcaddr) {
647 SIZE_T sz = __msan_get_socklen_t(addrlen);
648 __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
649 }
650 }
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000651 return res;
652}
653
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000654INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct msghdr *msg, int flags) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000655 ENSURE_MSAN_INITED();
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000656 SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000657 if (res > 0) {
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000658 for (SIZE_T i = 0; i < __msan_get_msghdr_iovlen(msg); ++i)
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000659 __msan_unpoison(__msan_get_msghdr_iov_iov_base(msg, i),
660 __msan_get_msghdr_iov_iov_len(msg, i));
661 }
662 return res;
663}
664
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000665INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000666 GET_MALLOC_STACK_TRACE;
667 if (!msan_inited) {
668 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000669 const SIZE_T kCallocPoolSize = 1024;
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000670 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000671 static SIZE_T allocated;
672 SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000673 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
674 allocated += size_in_words;
675 CHECK(allocated < kCallocPoolSize);
676 return mem;
677 }
678 return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true);
679}
680
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000681INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000682 GET_MALLOC_STACK_TRACE;
683 return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
684}
685
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000686INTERCEPTOR(void *, malloc, SIZE_T size) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000687 GET_MALLOC_STACK_TRACE;
688 return MsanReallocate(&stack, 0, size, sizeof(u64), false);
689}
690
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000691INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
692 int fd, OFF_T offset) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000693 ENSURE_MSAN_INITED();
694 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
695 if (res != (void*)-1)
696 __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
697 return res;
698}
699
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000700INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
701 int fd, OFF64_T offset) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000702 ENSURE_MSAN_INITED();
703 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
704 if (res != (void*)-1)
705 __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
706 return res;
707}
708
Evgeniy Stepanove3a32512013-01-17 13:42:17 +0000709struct dlinfo {
710 char *dli_fname;
711 void *dli_fbase;
712 char *dli_sname;
713 void *dli_saddr;
714};
715
716INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
717 ENSURE_MSAN_INITED();
718 int res = REAL(dladdr)(addr, info);
719 if (res != 0) {
720 __msan_unpoison(info, sizeof(*info));
721 if (info->dli_fname)
722 __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
723 if (info->dli_sname)
724 __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
725 }
726 return res;
727}
728
729INTERCEPTOR(int, getrusage, int who, void *usage) {
730 ENSURE_MSAN_INITED();
731 int res = REAL(getrusage)(who, usage);
732 if (res == 0) {
733 __msan_unpoison(usage, __msan::struct_rusage_sz);
734 }
735 return res;
736}
737
Evgeniy Stepanov222076e2013-01-18 11:17:23 +0000738#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
Kostya Serebryany69fe0ba2013-01-18 06:43:13 +0000739 __msan_unpoison(ptr, size)
Evgeniy Stepanov222076e2013-01-18 11:17:23 +0000740#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) do { } while (false)
Evgeniy Stepanov91181ea2013-01-18 11:38:23 +0000741#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
Evgeniy Stepanov01671c32013-01-18 13:12:56 +0000742 do { \
743 ctx = 0; \
744 (void)ctx; \
745 ENSURE_MSAN_INITED(); \
746 } while (false)
Evgeniy Stepanov222076e2013-01-18 11:17:23 +0000747#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
748#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
Evgeniy Stepanov01671c32013-01-18 13:12:56 +0000749#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
750 do { } while (false) // FIXME
Evgeniy Stepanova6c4a382013-01-18 13:01:18 +0000751#include "sanitizer_common/sanitizer_common_interceptors.inc"
Kostya Serebryany69fe0ba2013-01-18 06:43:13 +0000752
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000753// static
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000754void *fast_memset(void *ptr, int c, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000755 // hack until we have a really fast internal_memset
756 if (sizeof(uptr) == 8 &&
757 (n % 8) == 0 &&
758 ((uptr)ptr % 8) == 0 &&
759 (c == 0 || c == -1)) {
760 // Printf("memset %p %zd %x\n", ptr, n, c);
761 uptr to_store = c ? -1L : 0L;
762 uptr *p = (uptr*)ptr;
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000763 for (SIZE_T i = 0; i < n / 8; i++)
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000764 p[i] = to_store;
765 return ptr;
766 }
767 return internal_memset(ptr, c, n);
768}
769
770// static
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000771void *fast_memcpy(void *dst, const void *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000772 // Same hack as in fast_memset above.
773 if (sizeof(uptr) == 8 &&
774 (n % 8) == 0 &&
775 ((uptr)dst % 8) == 0 &&
776 ((uptr)src % 8) == 0) {
777 uptr *d = (uptr*)dst;
778 uptr *s = (uptr*)src;
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000779 for (SIZE_T i = 0; i < n / 8; i++)
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000780 d[i] = s[i];
781 return dst;
782 }
783 return internal_memcpy(dst, src, n);
784}
785
786// These interface functions reside here so that they can use
787// fast_memset, etc.
788void __msan_unpoison(void *a, uptr size) {
789 if (!MEM_IS_APP(a)) return;
790 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
791}
792
793void __msan_poison(void *a, uptr size) {
794 if (!MEM_IS_APP(a)) return;
795 fast_memset((void*)MEM_TO_SHADOW((uptr)a),
796 __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size);
797}
798
799void __msan_poison_stack(void *a, uptr size) {
800 if (!MEM_IS_APP(a)) return;
801 fast_memset((void*)MEM_TO_SHADOW((uptr)a),
802 __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size);
803}
804
805void __msan_clear_and_unpoison(void *a, uptr size) {
806 fast_memset(a, 0, size);
807 fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
808}
809
810void __msan_copy_origin(void *dst, const void *src, uptr size) {
811 if (!__msan_get_track_origins()) return;
812 if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
813 uptr d = MEM_TO_ORIGIN(dst);
814 uptr s = MEM_TO_ORIGIN(src);
815 uptr beg = d & ~3UL; // align down.
816 uptr end = (d + size + 3) & ~3UL; // align up.
817 s = s & ~3UL; // align down.
818 fast_memcpy((void*)beg, (void*)s, end - beg);
819}
820
821void __msan_copy_poison(void *dst, const void *src, uptr size) {
822 if (!MEM_IS_APP(dst)) return;
823 if (!MEM_IS_APP(src)) return;
824 fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst),
825 (void*)MEM_TO_SHADOW((uptr)src), size);
826 __msan_copy_origin(dst, src, size);
827}
828
829void __msan_move_poison(void *dst, const void *src, uptr size) {
830 if (!MEM_IS_APP(dst)) return;
831 if (!MEM_IS_APP(src)) return;
832 internal_memmove((void*)MEM_TO_SHADOW((uptr)dst),
833 (void*)MEM_TO_SHADOW((uptr)src), size);
834 __msan_copy_origin(dst, src, size);
835}
836
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000837void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000838 ENSURE_MSAN_INITED();
839 void *res = fast_memcpy(dest, src, n);
840 __msan_copy_poison(dest, src, n);
841 return res;
842}
843
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000844void *__msan_memset(void *s, int c, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000845 ENSURE_MSAN_INITED();
846 void *res = fast_memset(s, c, n);
847 __msan_unpoison(s, n);
848 return res;
849}
850
Kostya Serebryany07bb3922012-12-13 06:31:40 +0000851void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000852 ENSURE_MSAN_INITED();
853 void *res = REAL(memmove)(dest, src, n);
854 __msan_move_poison(dest, src, n);
855 return res;
856}
857
858namespace __msan {
859void InitializeInterceptors() {
860 static int inited = 0;
861 CHECK_EQ(inited, 0);
Kostya Serebryany69fe0ba2013-01-18 06:43:13 +0000862 SANITIZER_COMMON_INTERCEPTORS_INIT;
863
Alexey Samsonovcd1e68e2012-12-14 11:52:02 +0000864 INTERCEPT_FUNCTION(mmap);
865 INTERCEPT_FUNCTION(mmap64);
866 INTERCEPT_FUNCTION(posix_memalign);
867 INTERCEPT_FUNCTION(malloc);
868 INTERCEPT_FUNCTION(calloc);
869 INTERCEPT_FUNCTION(realloc);
870 INTERCEPT_FUNCTION(free);
871 INTERCEPT_FUNCTION(fread);
872 INTERCEPT_FUNCTION(fread_unlocked);
Alexey Samsonovcd1e68e2012-12-14 11:52:02 +0000873 INTERCEPT_FUNCTION(readlink);
874 INTERCEPT_FUNCTION(readdir);
875 INTERCEPT_FUNCTION(memcpy);
876 INTERCEPT_FUNCTION(memset);
877 INTERCEPT_FUNCTION(memmove);
878 INTERCEPT_FUNCTION(wmemset);
879 INTERCEPT_FUNCTION(wmemcpy);
880 INTERCEPT_FUNCTION(wmemmove);
881 INTERCEPT_FUNCTION(strcpy); // NOLINT
882 INTERCEPT_FUNCTION(strdup);
883 INTERCEPT_FUNCTION(strncpy); // NOLINT
884 INTERCEPT_FUNCTION(strlen);
885 INTERCEPT_FUNCTION(strnlen);
886 INTERCEPT_FUNCTION(gcvt);
887 INTERCEPT_FUNCTION(strcat); // NOLINT
888 INTERCEPT_FUNCTION(strncat); // NOLINT
889 INTERCEPT_FUNCTION(strtol);
890 INTERCEPT_FUNCTION(strtoll);
891 INTERCEPT_FUNCTION(strtoul);
892 INTERCEPT_FUNCTION(strtoull);
Evgeniy Stepanove3a32512013-01-17 13:42:17 +0000893 INTERCEPT_FUNCTION(strtod);
894 INTERCEPT_FUNCTION(strtof);
895 INTERCEPT_FUNCTION(strtold);
Alexey Samsonovcd1e68e2012-12-14 11:52:02 +0000896 INTERCEPT_FUNCTION(vsprintf);
897 INTERCEPT_FUNCTION(vsnprintf);
898 INTERCEPT_FUNCTION(vswprintf);
899 INTERCEPT_FUNCTION(sprintf); // NOLINT
900 INTERCEPT_FUNCTION(snprintf);
901 INTERCEPT_FUNCTION(swprintf);
902 INTERCEPT_FUNCTION(strftime);
903 INTERCEPT_FUNCTION(wcstombs);
904 INTERCEPT_FUNCTION(mbstowcs);
905 INTERCEPT_FUNCTION(wcslen);
906 INTERCEPT_FUNCTION(wcschr);
907 INTERCEPT_FUNCTION(wcscpy);
908 INTERCEPT_FUNCTION(wcscmp);
909 INTERCEPT_FUNCTION(wcstod);
910 INTERCEPT_FUNCTION(getenv);
911 INTERCEPT_FUNCTION(gettimeofday);
912 INTERCEPT_FUNCTION(fcvt);
913 INTERCEPT_FUNCTION(__fxstat);
914 INTERCEPT_FUNCTION(__xstat);
915 INTERCEPT_FUNCTION(__lxstat);
916 INTERCEPT_FUNCTION(__fxstat64);
917 INTERCEPT_FUNCTION(__xstat64);
918 INTERCEPT_FUNCTION(__lxstat64);
919 INTERCEPT_FUNCTION(pipe);
920 INTERCEPT_FUNCTION(wait);
921 INTERCEPT_FUNCTION(waitpid);
922 INTERCEPT_FUNCTION(fgets);
923 INTERCEPT_FUNCTION(fgets_unlocked);
924 INTERCEPT_FUNCTION(getcwd);
925 INTERCEPT_FUNCTION(realpath);
926 INTERCEPT_FUNCTION(getrlimit);
927 INTERCEPT_FUNCTION(getrlimit64);
928 INTERCEPT_FUNCTION(statfs);
929 INTERCEPT_FUNCTION(fstatfs);
930 INTERCEPT_FUNCTION(statfs64);
931 INTERCEPT_FUNCTION(fstatfs64);
932 INTERCEPT_FUNCTION(uname);
933 INTERCEPT_FUNCTION(epoll_wait);
934 INTERCEPT_FUNCTION(epoll_pwait);
935 INTERCEPT_FUNCTION(recv);
936 INTERCEPT_FUNCTION(recvfrom);
937 INTERCEPT_FUNCTION(recvmsg);
Evgeniy Stepanove3a32512013-01-17 13:42:17 +0000938 INTERCEPT_FUNCTION(dladdr);
939 INTERCEPT_FUNCTION(getrusage);
Evgeniy Stepanovc5033782012-12-11 12:27:27 +0000940 inited = 1;
941}
942} // namespace __msan