From eb37fcbc875d6aea445b187ec8871b842fb06a4a Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 7 Apr 2016 20:26:28 +0000 Subject: [PATCH] [sanitizer] Fix sem_init_glibc.cc test on __HAVE_64B_ATOMIC arches. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit glibc can use one of 2 layouts for semaphores: architectures that don't HAVE_64B_ATOMIC use an uint32_t field with semaphore value, then a private field, then a waiting thread count field - this is the layout currently assumed by the test. However, HAVE_64B_ATOMIC arches use a fused uint64_t field that contains the value in low bits and waiting thread count in high bits, followed by a private field. This resulted in taking private field from the wrong offset on 64-bit atomic platforms (the test still passed, but didn't actually test the private field). On big-endian platforms, this resulted in a fail, since the first 4 bytes overlay the thread count field, and not the value field. Found while porting ASan to s390x. Patch by Marcin Kościelnicki. llvm-svn: 265715 --- .../TestCases/Linux/sem_init_glibc.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) 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 index f17453b..193b33d 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc @@ -2,24 +2,35 @@ // 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 #include #include #include +#include -void my_sem_init(bool priv, int value, unsigned *a, unsigned char *b) { +// This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. +#if (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ + defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ + defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) +typedef uint64_t semval_t; +#else +typedef unsigned semval_t; +#endif + +void my_sem_init(bool priv, int value, semval_t *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)); + memcpy(a, p, sizeof(semval_t)); + memcpy(b, p + sizeof(semval_t), sizeof(char)); sem_destroy(&sem); } int main() { - unsigned a; + semval_t a; unsigned char b; my_sem_init(false, 42, &a, &b); -- 2.7.4