summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asan/asan_interceptors.cc3
-rw-r--r--lib/msan/msan_interceptors.cc9
-rw-r--r--lib/msan/tests/msan_test.cc17
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc44
-rw-r--r--lib/sanitizer_common/sanitizer_platform_interceptors.h2
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_posix.cc3
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_posix.h2
-rw-r--r--lib/tsan/rtl/tsan_stat.cc2
-rw-r--r--lib/tsan/rtl/tsan_stat.h2
9 files changed, 74 insertions, 10 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index b9b722e3a..a8e260bac 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -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)
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc
index aa3342ce2..13d67b72d 100644
--- a/lib/msan/msan_interceptors.cc
+++ b/lib/msan/msan_interceptors.cc
@@ -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);
diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc
index baf7956f5..b73e35c7d 100644
--- a/lib/msan/tests/msan_test.cc
+++ b/lib/msan/tests/msan_test.cc
@@ -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];
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 5c7de75e3..702e6bbd9 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -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;
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 6edb250a1..4a84e0547 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -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
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index 45218fc6b..abb661109 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -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);
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 91f2f112a..7258526b4 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -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;
diff --git a/lib/tsan/rtl/tsan_stat.cc b/lib/tsan/rtl/tsan_stat.cc
index 1ce60e79b..3f153b6e0 100644
--- a/lib/tsan/rtl/tsan_stat.cc
+++ b/lib/tsan/rtl/tsan_stat.cc
@@ -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 ";
diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h
index e57ce8d94..36b298e4d 100644
--- a/lib/tsan/rtl/tsan_stat.h
+++ b/lib/tsan/rtl/tsan_stat.h
@@ -344,6 +344,8 @@ enum StatType {
StatInt_wcsrtombs,
StatInt_wcsnrtombs,
StatInt_tcgetattr,
+ StatInt_realpath,
+ StatInt_canonicalize_file_name,
// Dynamic annotations.
StatAnnotation,