summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc19
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc5
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h12
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc32
4 files changed, 61 insertions, 7 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 7092aaa9d1b..4e653fa266d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -5114,21 +5114,26 @@ INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
#endif // SANITIZER_INTERCEPT_FOPENCOOKIE
#if SANITIZER_INTERCEPT_SEM
-INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) {
+INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
+ // Workaround a bug in glibc's "old" semaphore implementation by
+ // zero-initializing the sem_t contents. This has to be done here because
+ // interceptors bind to the lowest symbols version by default, hitting the
+ // buggy code path while the non-sanitized build of the same code works fine.
+ REAL(memset)(s, 0, sizeof(*s));
int res = REAL(sem_init)(s, pshared, value);
return res;
}
-INTERCEPTOR(int, sem_destroy, void *s) {
+INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
int res = REAL(sem_destroy)(s);
return res;
}
-INTERCEPTOR(int, sem_wait, void *s) {
+INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
@@ -5138,7 +5143,7 @@ INTERCEPTOR(int, sem_wait, void *s) {
return res;
}
-INTERCEPTOR(int, sem_trywait, void *s) {
+INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
@@ -5148,7 +5153,7 @@ INTERCEPTOR(int, sem_trywait, void *s) {
return res;
}
-INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
+INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
@@ -5159,7 +5164,7 @@ INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
return res;
}
-INTERCEPTOR(int, sem_post, void *s) {
+INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
@@ -5167,7 +5172,7 @@ INTERCEPTOR(int, sem_post, void *s) {
return res;
}
-INTERCEPTOR(int, sem_getvalue, void *s, int *sval) {
+INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
int res = REAL(sem_getvalue)(s, sval);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index 5f98099d1ce..9cfaec5cc8e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -122,6 +122,7 @@
# if defined(__mips64) || defined(__aarch64__)
# include <asm/ptrace.h>
# endif
+# include <semaphore.h>
#endif
#if !SANITIZER_ANDROID
@@ -1241,4 +1242,8 @@ CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, seek);
CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close);
#endif
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+CHECK_TYPE_SIZE(sem_t);
+#endif
+
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index a2d01e2f6f2..c598fe0d716 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -150,6 +150,18 @@ namespace __sanitizer {
};
const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+ struct __sanitizer_sem_t {
+#if SANITIZER_ANDROID && defined(_LP64)
+ int data[4];
+#elif SANITIZER_ANDROID && !defined(_LP64)
+ int data;
+#elif SANITIZER_LINUX
+ uptr data[4];
+#elif SANITIZER_FREEBSD
+ u32 data[4];
+#endif
+ };
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_ANDROID
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
new file mode 100644
index 00000000000..f17453b2d51
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
@@ -0,0 +1,32 @@
+// RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t
+// This test depends on the glibc layout of struct sem_t and checks that we
+// don't leave sem_t::private uninitialized.
+// UNSUPPORTED: android
+#include <assert.h>
+#include <semaphore.h>
+#include <string.h>
+
+void my_sem_init(bool priv, int value, unsigned *a, unsigned char *b) {
+ sem_t sem;
+ memset(&sem, 0xAB, sizeof(sem));
+ sem_init(&sem, priv, value);
+
+ char *p = (char *)&sem;
+ memcpy(a, p, sizeof(unsigned));
+ memcpy(b, p + sizeof(unsigned), sizeof(char));
+
+ sem_destroy(&sem);
+}
+
+int main() {
+ unsigned a;
+ unsigned char b;
+
+ my_sem_init(false, 42, &a, &b);
+ assert(a == 42);
+ assert(b != 0xAB);
+
+ my_sem_init(true, 43, &a, &b);
+ assert(a == 43);
+ assert(b != 0xAB);
+}
OpenPOWER on IntegriCloud