[sanitizer] Add interceptors for localtime and friends.

llvm-svn: 175499
This commit is contained in:
Evgeniy Stepanov 2013-02-19 09:19:16 +00:00
parent 3e62fe8c23
commit ea61d08185
11 changed files with 212 additions and 51 deletions

View File

@ -195,6 +195,20 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create,
void *(*start_routine)(void*), void *arg);
# endif
# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep);
DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep,
void *result);
DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep);
DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep,
void *result);
DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep);
DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep,
char *result);
DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm);
DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result);
# endif
// stdio.h
# if SANITIZER_INTERCEPT_SCANF
DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap);

View File

@ -7,7 +7,6 @@ set(MSAN_RTL_SOURCES
msan_interceptors.cc
msan_linux.cc
msan_new_delete.cc
msan_platform_limits_posix.cc
msan_report.cc
)
set(MSAN_RTL_CFLAGS

View File

@ -17,7 +17,7 @@
#include "interception/interception.h"
#include "msan.h"
#include "msan_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@ -87,7 +87,7 @@ INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
INTERCEPTOR(void *, readdir, void *a) {
ENSURE_MSAN_INITED();
void *res = REAL(readdir)(a);
__msan_unpoison(res, __msan::struct_dirent_sz);
__msan_unpoison(res, __sanitizer::struct_dirent_sz);
return res;
}
@ -452,7 +452,7 @@ INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__fxstat)(magic, fd, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat_sz);
__msan_unpoison(buf, __sanitizer::struct_stat_sz);
return res;
}
@ -460,7 +460,7 @@ INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__fxstat64)(magic, fd, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat64_sz);
__msan_unpoison(buf, __sanitizer::struct_stat64_sz);
return res;
}
@ -468,7 +468,7 @@ INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__xstat)(magic, path, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat_sz);
__msan_unpoison(buf, __sanitizer::struct_stat_sz);
return res;
}
@ -476,7 +476,7 @@ INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__xstat64)(magic, path, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat64_sz);
__msan_unpoison(buf, __sanitizer::struct_stat64_sz);
return res;
}
@ -484,7 +484,7 @@ INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__lxstat)(magic, path, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat_sz);
__msan_unpoison(buf, __sanitizer::struct_stat_sz);
return res;
}
@ -492,7 +492,7 @@ INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__lxstat64)(magic, path, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_stat64_sz);
__msan_unpoison(buf, __sanitizer::struct_stat64_sz);
return res;
}
@ -562,7 +562,7 @@ INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
ENSURE_MSAN_INITED();
int res = REAL(getrlimit)(resource, rlim);
if (!res)
__msan_unpoison(rlim, __msan::struct_rlimit_sz);
__msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
return res;
}
@ -572,7 +572,7 @@ INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
ENSURE_MSAN_INITED();
int res = REAL(getrlimit64)(resource, rlim);
if (!res)
__msan_unpoison(rlim, __msan::struct_rlimit64_sz);
__msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
return res;
}
@ -580,7 +580,7 @@ INTERCEPTOR(int, statfs, const char *s, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(statfs)(s, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_statfs_sz);
__msan_unpoison(buf, __sanitizer::struct_statfs_sz);
return res;
}
@ -588,7 +588,7 @@ INTERCEPTOR(int, fstatfs, int fd, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(fstatfs)(fd, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_statfs_sz);
__msan_unpoison(buf, __sanitizer::struct_statfs_sz);
return res;
}
@ -596,7 +596,7 @@ INTERCEPTOR(int, statfs64, const char *s, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(statfs64)(s, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_statfs64_sz);
__msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
return res;
}
@ -604,7 +604,7 @@ INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(fstatfs64)(fd, buf);
if (!res)
__msan_unpoison(buf, __msan::struct_statfs64_sz);
__msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
return res;
}
@ -612,7 +612,7 @@ INTERCEPTOR(int, uname, void *utsname) {
ENSURE_MSAN_INITED();
int res = REAL(uname)(utsname);
if (!res) {
__msan_unpoison(utsname, __msan::struct_utsname_sz);
__msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
}
return res;
}
@ -634,7 +634,7 @@ INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
ENSURE_MSAN_INITED();
int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
if (res > 0) {
__msan_unpoison(events, __msan::struct_epoll_event_sz * res);
__msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
}
return res;
}
@ -644,7 +644,7 @@ INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
ENSURE_MSAN_INITED();
int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
if (res > 0) {
__msan_unpoison(events, __msan::struct_epoll_event_sz * res);
__msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
}
return res;
}
@ -662,12 +662,12 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
ENSURE_MSAN_INITED();
SIZE_T srcaddr_sz;
if (srcaddr)
srcaddr_sz = __msan_get_socklen_t(addrlen);
srcaddr_sz = __sanitizer_get_socklen_t(addrlen);
SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
if (res > 0) {
__msan_unpoison(buf, res);
if (srcaddr) {
SIZE_T sz = __msan_get_socklen_t(addrlen);
SIZE_T sz = __sanitizer_get_socklen_t(addrlen);
__msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
}
}
@ -678,9 +678,9 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct msghdr *msg, int flags) {
ENSURE_MSAN_INITED();
SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
if (res > 0) {
for (SIZE_T i = 0; i < __msan_get_msghdr_iovlen(msg); ++i)
__msan_unpoison(__msan_get_msghdr_iov_iov_base(msg, i),
__msan_get_msghdr_iov_iov_len(msg, i));
for (SIZE_T i = 0; i < __sanitizer_get_msghdr_iovlen(msg); ++i)
__msan_unpoison(__sanitizer_get_msghdr_iov_iov_base(msg, i),
__sanitizer_get_msghdr_iov_iov_len(msg, i));
}
return res;
}
@ -766,7 +766,7 @@ INTERCEPTOR(int, getrusage, int who, void *usage) {
ENSURE_MSAN_INITED();
int res = REAL(getrusage)(who, usage);
if (res == 0) {
__msan_unpoison(usage, __msan::struct_rusage_sz);
__msan_unpoison(usage, __sanitizer::struct_rusage_sz);
}
return res;
}

View File

@ -807,6 +807,27 @@ TEST(MemorySanitizer, gettimeofday) {
EXPECT_NOT_POISONED(tz.tz_dsttime);
}
TEST(MemorySanitizer, localtime) {
time_t t = 123;
struct tm *time = localtime(&t);
assert(time != 0);
EXPECT_NOT_POISONED(time->tm_sec);
EXPECT_NOT_POISONED(time->tm_hour);
EXPECT_NOT_POISONED(time->tm_year);
EXPECT_NOT_POISONED(time->tm_isdst);
}
TEST(MemorySanitizer, localtime_r) {
time_t t = 123;
struct tm time;
struct tm *res = localtime_r(&t, &time);
assert(res != 0);
EXPECT_NOT_POISONED(time.tm_sec);
EXPECT_NOT_POISONED(time.tm_hour);
EXPECT_NOT_POISONED(time.tm_year);
EXPECT_NOT_POISONED(time.tm_isdst);
}
TEST(MemorySanitizer, mmap) {
const int size = 4096;
void *p1, *p2;

View File

@ -8,6 +8,7 @@ set(SANITIZER_SOURCES
sanitizer_libc.cc
sanitizer_linux.cc
sanitizer_mac.cc
sanitizer_platform_limits_posix.cc
sanitizer_posix.cc
sanitizer_printf.cc
sanitizer_stackdepot.cc

View File

@ -146,6 +146,100 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2,
#define INIT_PRCTL
#endif // SANITIZER_INTERCEPT_PRCTL
#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
INTERCEPTOR(void *, localtime, unsigned long *timep) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
void *res = REAL(localtime)(timep);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
}
return res;
}
INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
void *res = REAL(localtime_r)(timep, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
}
return res;
}
INTERCEPTOR(void *, gmtime, unsigned long *timep) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
void *res = REAL(gmtime)(timep);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
}
return res;
}
INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
void *res = REAL(gmtime_r)(timep, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
}
return res;
}
INTERCEPTOR(char *, ctime, unsigned long *timep) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
char *res = REAL(ctime)(timep);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
}
return res;
}
INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
char *res = REAL(ctime_r)(timep, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
}
return res;
}
INTERCEPTOR(char *, asctime, void *tm) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
char *res = REAL(asctime)(tm);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
}
return res;
}
INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
char *res = REAL(asctime_r)(tm, result);
if (res) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
}
return res;
}
#define INIT_LOCALTIME_AND_FRIENDS \
INTERCEPT_FUNCTION(localtime); \
INTERCEPT_FUNCTION(localtime_r); \
INTERCEPT_FUNCTION(gmtime); \
INTERCEPT_FUNCTION(gmtime_r); \
INTERCEPT_FUNCTION(ctime); \
INTERCEPT_FUNCTION(ctime_r); \
INTERCEPT_FUNCTION(asctime); \
INTERCEPT_FUNCTION(asctime_r);
#else
#define INIT_LOCALTIME_AND_FRIENDS
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
#if SANITIZER_INTERCEPT_SCANF
#include "sanitizer_common_interceptors_scanf.inc"
@ -237,4 +331,5 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
INIT_WRITE; \
INIT_PWRITE; \
INIT_PWRITE64; \
INIT_LOCALTIME_AND_FRIENDS; \
INIT_SCANF;

View File

@ -16,6 +16,7 @@
#if !defined(_WIN32)
# define SI_NOT_WINDOWS 1
# include "sanitizer_platform_limits_posix.h"
#else
# define SI_NOT_WINDOWS 0
#endif
@ -35,4 +36,6 @@
# define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
# define SANITIZER_INTERCEPT_PRCTL SI_LINUX_NOT_ANDROID
# define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS

View File

@ -1,4 +1,4 @@
//===-- msan_platform_limits.cc -------------------------------------------===//
//===-- sanitizer_platform_limits_posix.cc --------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -7,53 +7,61 @@
//
//===----------------------------------------------------------------------===//
//
// This file is a part of MemorySanitizer.
// This file is a part of Sanitizer common code.
//
// Sizes and layouts of platform-specific POSIX data structures.
//===----------------------------------------------------------------------===//
#ifdef __linux__
#if defined(__linux__) || defined(__APPLE__)
#include "msan.h"
#include "msan_platform_limits_posix.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_platform_limits_posix.h"
#include <dirent.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <time.h>
#if defined(__linux__)
#include <sys/vfs.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <dirent.h>
#endif // __linux__
namespace __msan {
namespace __sanitizer {
unsigned struct_utsname_sz = sizeof(struct utsname);
unsigned struct_stat_sz = sizeof(struct stat);
unsigned struct_stat64_sz = sizeof(struct stat64);
unsigned struct_rusage_sz = sizeof(struct rusage);
unsigned struct_tm_sz = sizeof(struct tm);
#if defined(__linux__)
unsigned struct_rlimit_sz = sizeof(struct rlimit);
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_dirent_sz = sizeof(struct dirent);
unsigned struct_statfs_sz = sizeof(struct statfs);
unsigned struct_statfs64_sz = sizeof(struct statfs64);
unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
unsigned struct_rusage_sz = sizeof(struct rusage);
#endif // __linux__
void* __msan_get_msghdr_iov_iov_base(void* msg, int idx) {
void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx) {
return ((struct msghdr *)msg)->msg_iov[idx].iov_base;
}
uptr __msan_get_msghdr_iov_iov_len(void* msg, int idx) {
uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx) {
return ((struct msghdr *)msg)->msg_iov[idx].iov_len;
}
uptr __msan_get_msghdr_iovlen(void* msg) {
uptr __sanitizer_get_msghdr_iovlen(void* msg) {
return ((struct msghdr *)msg)->msg_iovlen;
}
uptr __msan_get_socklen_t(void* socklen_ptr) {
uptr __sanitizer_get_socklen_t(void* socklen_ptr) {
return *(socklen_t*)socklen_ptr;
}
} // namespace __msan
} // namespace __sanitizer
#endif // __linux__
#endif // __linux__ || __APPLE__

View File

@ -1,4 +1,4 @@
//===-- msan_platform_limits.h ----------------------------------*- C++ -*-===//
//===-- sanitizer_platform_limits_posix.h ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -7,30 +7,34 @@
//
//===----------------------------------------------------------------------===//
//
// This file is a part of MemorySanitizer.
// This file is a part of Sanitizer common code.
//
// Sizes and layouts of platform-specific data structures.
// Sizes and layouts of platform-specific POSIX data structures.
//===----------------------------------------------------------------------===//
#ifndef MSAN_PLATFORM_LIMITS_H
#define MSAN_PLATFORM_LIMITS_H
#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
#define SANITIZER_PLATFORM_LIMITS_POSIX_H
namespace __msan {
namespace __sanitizer {
extern unsigned struct_utsname_sz;
extern unsigned struct_stat_sz;
extern unsigned struct_stat64_sz;
extern unsigned struct_rusage_sz;
extern unsigned struct_tm_sz;
#if defined(__linux__)
extern unsigned struct_rlimit_sz;
extern unsigned struct_rlimit64_sz;
extern unsigned struct_dirent_sz;
extern unsigned struct_statfs_sz;
extern unsigned struct_statfs64_sz;
extern unsigned struct_epoll_event_sz;
extern unsigned struct_rusage_sz;
#endif // __linux__
void* __msan_get_msghdr_iov_iov_base(void* msg, int idx);
uptr __msan_get_msghdr_iov_iov_len(void* msg, int idx);
uptr __msan_get_msghdr_iovlen(void* msg);
uptr __msan_get_socklen_t(void* socklen_ptr);
} // namespace __msan
void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx);
uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx);
uptr __sanitizer_get_msghdr_iovlen(void* msg);
uptr __sanitizer_get_socklen_t(void* socklen_ptr);
} // namespace __sanitizer
#endif

View File

@ -265,6 +265,14 @@ void StatOutput(u64 *stat) {
name[StatInt___isoc99_fscanf] = " fscanf ";
name[StatInt_on_exit] = " on_exit ";
name[StatInt___cxa_atexit] = " __cxa_atexit ";
name[StatInt_localtime] = " localtime ";
name[StatInt_localtime_r] = " localtime_r ";
name[StatInt_gmtime] = " gmtime ";
name[StatInt_gmtime_r] = " gmtime_r ";
name[StatInt_ctime] = " ctime ";
name[StatInt_ctime_r] = " ctime_r ";
name[StatInt_asctime] = " asctime ";
name[StatInt_asctime_r] = " asctime_r ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";

View File

@ -264,6 +264,14 @@ enum StatType {
StatInt___isoc99_fscanf,
StatInt_on_exit,
StatInt___cxa_atexit,
StatInt_localtime,
StatInt_localtime_r,
StatInt_gmtime,
StatInt_gmtime_r,
StatInt_ctime,
StatInt_ctime_r,
StatInt_asctime,
StatInt_asctime_r,
// Dynamic annotations.
StatAnnotation,