Home | History | Annotate | Line # | Download | only in c++
t_tsan_vptr_race.sh revision 1.2.2.2
      1 # Copyright (c) 2018 The NetBSD Foundation, Inc.
      2 # All rights reserved.
      3 #
      4 # This code is derived from software contributed to The NetBSD Foundation
      5 # by Yang Zheng.
      6 #
      7 # Redistribution and use in source and binary forms, with or without
      8 # modification, are permitted provided that the following conditions
      9 # are met:
     10 # 1. Redistributions of source code must retain the above copyright
     11 #    notice, this list of conditions and the following disclaimer.
     12 # 2. Redistributions in binary form must reproduce the above copyright
     13 #    notice, this list of conditions and the following disclaimer in the
     14 #    documentation and/or other materials provided with the distribution.
     15 #
     16 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26 # POSSIBILITY OF SUCH DAMAGE.
     27 #
     28 
     29 test_target()
     30 {
     31 	SUPPORT='n'
     32 	if uname -m | grep -q "amd64" && command -v c++ >/dev/null 2>&1 && \
     33 		   ! echo __clang__ | c++ -E - | grep -q __clang__; then
     34 		# only clang with major version newer than 7 is supported
     35 		CLANG_MAJOR=`echo __clang_major__ | c++ -E - | grep -o '^[[:digit:]]'`
     36 		if [ "$CLANG_MAJOR" -ge "7" ]; then
     37 			SUPPORT='y'
     38 		fi
     39 	fi
     40 }
     41 
     42 atf_test_case vptr_race
     43 vptr_race_head() {
     44 	atf_set "descr" "Test thread sanitizer for vptr race condition"
     45 	atf_set "require.progs" "c++ paxctl"
     46 }
     47 
     48 atf_test_case vptr_race_profile
     49 vptr_race_profile_head() {
     50 	atf_set "descr" "Test thread sanitizer for vptr race with profiling option"
     51 	atf_set "require.progs" "c++ paxctl"
     52 }
     53 atf_test_case vptr_race_pic
     54 vptr_race_pic_head() {
     55 	atf_set "descr" "Test thread sanitizer for vptr race with position independent code (PIC) flag"
     56 	atf_set "require.progs" "c++ paxctl"
     57 }
     58 atf_test_case vptr_race_pie
     59 vptr_race_pie_head() {
     60 	atf_set "descr" "Test thread sanitizer for vptr race with position independent execution (PIE) flag"
     61 	atf_set "require.progs" "c++ paxctl"
     62 }
     63 
     64 vptr_race_body(){
     65 	cat > test.cc << EOF
     66 #include <pthread.h>
     67 pthread_barrier_t barrier;
     68 struct A {
     69   volatile bool done;
     70   A(): done(false) { }
     71   virtual void Done() { done = true; }
     72   virtual ~A() { while (!done) ; }
     73 };
     74 struct B: A {};
     75 A *obj = new B;
     76 void *Thread1(void *x) {
     77   pthread_barrier_wait(&barrier);
     78   obj->Done();
     79   return NULL;
     80 }
     81 int main() {
     82   pthread_barrier_init(&barrier, NULL, 2);
     83   pthread_t t;
     84   pthread_create(&t, NULL, Thread1, NULL);
     85   pthread_barrier_wait(&barrier);
     86   delete obj;
     87   pthread_join(t, NULL);
     88   return 0;
     89 }
     90 EOF
     91 
     92 	c++ -fsanitize=thread -o test test.cc
     93 	paxctl +a test
     94 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: data race on vptr \(ctor/dtor vs virtual call\)" ./test
     95 }
     96 
     97 vptr_race_profile_body(){
     98 	cat > test.cc << EOF
     99 #include <pthread.h>
    100 pthread_barrier_t barrier;
    101 struct A {
    102   volatile bool done;
    103   A(): done(false) { }
    104   virtual void Done() { done = true; }
    105   virtual ~A() { while (!done) ; }
    106 };
    107 struct B: A {};
    108 A *obj = new B;
    109 void *Thread1(void *x) {
    110   pthread_barrier_wait(&barrier);
    111   obj->Done();
    112   return NULL;
    113 }
    114 int main() {
    115   pthread_barrier_init(&barrier, NULL, 2);
    116   pthread_t t;
    117   pthread_create(&t, NULL, Thread1, NULL);
    118   pthread_barrier_wait(&barrier);
    119   delete obj;
    120   pthread_join(t, NULL);
    121   return 0;
    122 }
    123 EOF
    124 
    125 	c++ -fsanitize=thread -o test -pg test.cc
    126 	paxctl +a test
    127 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: data race on vptr \(ctor/dtor vs virtual call\)" ./test
    128 }
    129 
    130 vptr_race_pic_body(){
    131 	cat > test.cc << EOF
    132 #include <stdio.h>
    133 #include <stdlib.h>
    134 int help(int);
    135 int main(int argc, char **argv) {return help(argc);}
    136 EOF
    137 
    138 	cat > pic.cc << EOF
    139 #include <pthread.h>
    140 pthread_barrier_t barrier;
    141 struct A {
    142   volatile bool done;
    143   A(): done(false) { }
    144   virtual void Done() { done = true; }
    145   virtual ~A() { while (!done) ; }
    146 };
    147 struct B: A {};
    148 A *obj = new B;
    149 void *Thread1(void *x) {
    150   pthread_barrier_wait(&barrier);
    151   obj->Done();
    152   return NULL;
    153 }
    154 int help(int argc) {
    155   pthread_barrier_init(&barrier, NULL, 2);
    156   pthread_t t;
    157   pthread_create(&t, NULL, Thread1, NULL);
    158   pthread_barrier_wait(&barrier);
    159   delete obj;
    160   pthread_join(t, NULL);
    161   return 0;
    162 }
    163 EOF
    164 
    165 	c++ -fsanitize=thread -fPIC -shared -o libtest.so pic.cc
    166 	c++ -o test test.cc -fsanitize=thread -L. -ltest
    167 	paxctl +a test
    168 
    169 	export LD_LIBRARY_PATH=.
    170 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: data race on vptr \(ctor/dtor vs virtual call\)" ./test
    171 }
    172 vptr_race_pie_body(){
    173 	
    174 	#check whether -pie flag is supported on this architecture
    175 	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then 
    176 		atf_set_skip "c++ -pie not supported on this architecture"
    177 	fi
    178 	cat > test.cc << EOF
    179 #include <pthread.h>
    180 pthread_barrier_t barrier;
    181 struct A {
    182   volatile bool done;
    183   A(): done(false) { }
    184   virtual void Done() { done = true; }
    185   virtual ~A() { while (!done) ; }
    186 };
    187 struct B: A {};
    188 A *obj = new B;
    189 void *Thread1(void *x) {
    190   pthread_barrier_wait(&barrier);
    191   obj->Done();
    192   return NULL;
    193 }
    194 int main() {
    195   pthread_barrier_init(&barrier, NULL, 2);
    196   pthread_t t;
    197   pthread_create(&t, NULL, Thread1, NULL);
    198   pthread_barrier_wait(&barrier);
    199   delete obj;
    200   pthread_join(t, NULL);
    201   return 0;
    202 }
    203 EOF
    204 
    205 	c++ -fsanitize=thread -o test -fpie -pie test.cc
    206 	paxctl +a test
    207 	atf_check -s ignore -o ignore -e match:"WARNING: ThreadSanitizer: data race on vptr \(ctor/dtor vs virtual call\)" ./test
    208 }
    209 
    210 
    211 atf_test_case target_not_supported
    212 target_not_supported_head()
    213 {
    214 	atf_set "descr" "Test forced skip"
    215 }
    216 
    217 target_not_supported_body()
    218 {
    219 	atf_skip "Target is not supported"
    220 }
    221 
    222 atf_init_test_cases()
    223 {
    224 	test_target
    225 	test $SUPPORT = 'n' && {
    226 		atf_add_test_case target_not_supported
    227 		return 0
    228 	}
    229 	atf_add_test_case vptr_race
    230 	atf_add_test_case vptr_race_profile
    231 	atf_add_test_case vptr_race_pie
    232 	atf_add_test_case vptr_race_pic
    233 }
    234