t_tsan_vptr_race.sh revision 1.1
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
29test_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
42atf_test_case vptr_race
43vptr_race_head() {
44	atf_set "descr" "Test thread sanitizer for vptr race condition"
45	atf_set "require.progs" "c++ paxctl"
46}
47
48atf_test_case vptr_race_profile
49vptr_race_profile_head() {
50	atf_set "descr" "Test thread sanitizer for vptr race with profiling option"
51	atf_set "require.progs" "c++ paxctl"
52}
53atf_test_case vptr_race_pic
54vptr_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}
58atf_test_case vptr_race_pie
59vptr_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
64vptr_race_body(){
65	cat > test.cc << EOF
66#include <pthread.h>
67pthread_barrier_t barrier;
68struct A {
69  volatile bool done;
70  A(): done(false) { }
71  virtual void Done() { done = true; }
72  virtual ~A() { while (!done) ; }
73};
74struct B: A {};
75A *obj = new B;
76void *Thread1(void *x) {
77  pthread_barrier_wait(&barrier);
78  obj->Done();
79  return NULL;
80}
81int 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}
90EOF
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
97vptr_race_profile_body(){
98	cat > test.cc << EOF
99#include <pthread.h>
100pthread_barrier_t barrier;
101struct A {
102  volatile bool done;
103  A(): done(false) { }
104  virtual void Done() { done = true; }
105  virtual ~A() { while (!done) ; }
106};
107struct B: A {};
108A *obj = new B;
109void *Thread1(void *x) {
110  pthread_barrier_wait(&barrier);
111  obj->Done();
112  return NULL;
113}
114int 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}
123EOF
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
130vptr_race_pic_body(){
131	cat > test.cc << EOF
132#include <stdio.h>
133#include <stdlib.h>
134int help(int);
135int main(int argc, char **argv) {return help(argc);}
136EOF
137
138	cat > pic.cc << EOF
139#include <pthread.h>
140pthread_barrier_t barrier;
141struct A {
142  volatile bool done;
143  A(): done(false) { }
144  virtual void Done() { done = true; }
145  virtual ~A() { while (!done) ; }
146};
147struct B: A {};
148A *obj = new B;
149void *Thread1(void *x) {
150  pthread_barrier_wait(&barrier);
151  obj->Done();
152  return NULL;
153}
154int 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}
163EOF
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}
172vptr_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>
180pthread_barrier_t barrier;
181struct A {
182  volatile bool done;
183  A(): done(false) { }
184  virtual void Done() { done = true; }
185  virtual ~A() { while (!done) ; }
186};
187struct B: A {};
188A *obj = new B;
189void *Thread1(void *x) {
190  pthread_barrier_wait(&barrier);
191  obj->Done();
192  return NULL;
193}
194int 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}
203EOF
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
211atf_test_case target_not_supported
212target_not_supported_head()
213{
214	atf_set "descr" "Test forced skip"
215}
216
217atf_init_test_cases()
218{
219	test_target
220	test $SUPPORT = 'n' && {
221		atf_add_test_case target_not_supported
222		return 0
223	}
224	atf_add_test_case vptr_race
225	atf_add_test_case vptr_race_profile
226	atf_add_test_case vptr_race_pie
227	atf_add_test_case vptr_race_pic
228}
229