[sanitizer] Intercept realpath and canonicalize_file_name.

Handle realpath(path, NULL) form.

llvm-svn: 185921
This commit is contained in:
Evgeniy Stepanov 2013-07-09 09:53:37 +00:00
parent f60c75a644
commit 77ef78a0a5
9 changed files with 74 additions and 10 deletions

View File

@ -99,6 +99,9 @@ void SetThreadName(const char *name) {
// ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
ASAN_WRITE_RANGE(ptr, size)
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)

View File

@ -619,14 +619,6 @@ INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
return res;
}
INTERCEPTOR(char *, realpath, char *path, char *abspath) {
ENSURE_MSAN_INITED();
char *res = REAL(realpath)(path, abspath);
if (res)
__msan_unpoison(abspath, REAL(strlen)(abspath) + 1);
return res;
}
INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
if (msan_init_is_running)
return REAL(getrlimit)(resource, rlim);
@ -1208,7 +1200,6 @@ void InitializeInterceptors() {
INTERCEPT_FUNCTION(socketpair);
INTERCEPT_FUNCTION(fgets);
INTERCEPT_FUNCTION(fgets_unlocked);
INTERCEPT_FUNCTION(realpath);
INTERCEPT_FUNCTION(getrlimit);
INTERCEPT_FUNCTION(getrlimit64);
INTERCEPT_FUNCTION(statfs);

View File

@ -939,6 +939,23 @@ TEST(MemorySanitizer, realpath) {
EXPECT_NOT_POISONED(path[0]);
}
TEST(MemorySanitizer, realpath_null) {
const char* relpath = ".";
char* res = realpath(relpath, NULL);
printf("%d, %s\n", errno, strerror(errno));
assert(res);
EXPECT_NOT_POISONED(res[0]);
free(res);
}
TEST(MemorySanitizer, canonicalize_file_name) {
const char* relpath = ".";
char* res = canonicalize_file_name(relpath);
assert(res);
EXPECT_NOT_POISONED(res[0]);
free(res);
}
TEST(MemorySanitizer, memcpy) {
char* x = new char[2];
char* y = new char[2];

View File

@ -1580,6 +1580,46 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
#define INIT_TCGETATTR
#endif
#if SANITIZER_INTERCEPT_REALPATH
INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
// Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
// version of a versioned symbol. For realpath(), this gives us something
// (called __old_realpath) that does not handle NULL in the second argument.
// Handle it as part of the interceptor.
char *allocated_path = 0;
if (!resolved_path)
allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
char *res = REAL(realpath)(path, resolved_path);
if (allocated_path && !res)
WRAP(free)(allocated_path);
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
return res;
}
#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
#else
#define INIT_REALPATH
#endif
#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
char *res = REAL(canonicalize_file_name)(path);
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
return res;
}
#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
#else
#define INIT_CANONICALIZE_FILE_NAME
#endif
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
INIT_STRCASECMP; \
INIT_STRNCASECMP; \
@ -1634,4 +1674,6 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
INIT_MBSNRTOWCS; \
INIT_WCSTOMBS; \
INIT_WCSNRTOMBS; \
INIT_TCGETATTR;
INIT_TCGETATTR; \
INIT_REALPATH; \
INIT_CANONICALIZE_FILE_NAME;

View File

@ -106,5 +106,7 @@
# define SANITIZER_INTERCEPT_WCSTOMBS SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_WCSNRTOMBS SI_MAC || SI_LINUX_NOT_ANDROID
# define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX
# define SANITIZER_INTERCEPT_REALPATH SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -22,6 +22,7 @@
#include <arpa/inet.h>
#include <dirent.h>
#include <grp.h>
#include <limits.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>
@ -194,6 +195,8 @@ namespace __sanitizer {
#endif
#endif
unsigned path_max = PATH_MAX;
// ioctl arguments
unsigned struct_arpreq_sz = sizeof(struct arpreq);
unsigned struct_ifreq_sz = sizeof(struct ifreq);

View File

@ -195,6 +195,8 @@ namespace __sanitizer {
extern int glob_nomatch;
#endif
extern unsigned path_max;
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
(defined(__i386) || defined (__x86_64))
extern unsigned struct_user_regs_struct_sz;

View File

@ -349,6 +349,8 @@ void StatOutput(u64 *stat) {
name[StatInt_wcsrtombs] = " wcsrtombs ";
name[StatInt_wcsnrtombs] = " wcsnrtombs ";
name[StatInt_tcgetattr] = " tcgetattr ";
name[StatInt_realpath] = " realpath ";
name[StatInt_canonicalize_file_name] = " canonicalize_file_name ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";

View File

@ -344,6 +344,8 @@ enum StatType {
StatInt_wcsrtombs,
StatInt_wcsnrtombs,
StatInt_tcgetattr,
StatInt_realpath,
StatInt_canonicalize_file_name,
// Dynamic annotations.
StatAnnotation,