xref: /netbsd-src/tests/lib/libc/misc/t_ubsan.c (revision ed08d308245cf036b41e935f901709a030cdf975)
1 /*	$NetBSD: t_ubsan.c,v 1.6 2019/10/28 18:10:22 joerg Exp $	*/
2 
3 /*-
4  * Copyright (c) 2018 The NetBSD Foundation, Inc.
5  * All rights reserved.
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 #include <sys/cdefs.h>
30 __COPYRIGHT("@(#) Copyright (c) 2018\
31  The NetBSD Foundation, inc. All rights reserved.");
32 __RCSID("$NetBSD: t_ubsan.c,v 1.6 2019/10/28 18:10:22 joerg Exp $");
33 
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 
37 #include <limits.h>
38 #include <signal.h>
39 #include <stdbool.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44 
45 #ifdef __cplusplus
46 #include <atf-c++.hpp>
47 #define UBSAN_TC(a)			ATF_TEST_CASE(a)
48 #define UBSAN_TC_HEAD(a, b)		ATF_TEST_CASE_HEAD(a)
49 #define UBSAN_TC_BODY(a, b)		ATF_TEST_CASE_BODY(a)
50 #define UBSAN_CASES(a)			ATF_INIT_TEST_CASES(a)
51 #define UBSAN_TEST_CASE(a, b)		ATF_ADD_TEST_CASE(a, b)
52 #define UBSAN_MD_VAR(a, b, c)		set_md_var(b, c)
53 #define REINTERPRET_CAST(__dt, __st)	reinterpret_cast<__dt>(__st)
54 #define STATIC_CAST(__dt, __st)		static_cast<__dt>(__st)
55 #else
56 #include <atf-c.h>
57 #define UBSAN_TC(a)			ATF_TC(a)
58 #define UBSAN_TC_HEAD(a, b)		ATF_TC_HEAD(a, b)
59 #define UBSAN_TC_BODY(a, b)		ATF_TC_BODY(a, b)
60 #define UBSAN_CASES(a)			ATF_TP_ADD_TCS(a)
61 #define UBSAN_TEST_CASE(a, b)		ATF_TP_ADD_TC(a, b)
62 #define UBSAN_MD_VAR(a, b, c)		atf_tc_set_md_var(a, b, c)
63 #define REINTERPRET_CAST(__dt, __st)	((__dt)(__st))
64 #define STATIC_CAST(__dt, __st)		((__dt)(__st))
65 #endif
66 
67 #ifdef ENABLE_TESTS
68 static void
test_case(void (* fun)(void),const char * string)69 test_case(void (*fun)(void), const char *string)
70 {
71 	int filedes[2];
72 	pid_t pid;
73 	FILE *fp;
74 	size_t len;
75 	char *buffer;
76 	int status;
77 
78 	/*
79 	 * Spawn a subprocess that triggers the issue.
80 	 * A child process either exits or is signaled with a crash signal.
81 	 */
82 	ATF_REQUIRE_EQ(pipe(filedes), 0);
83 	pid = fork();
84 	ATF_REQUIRE(pid != -1);
85 	if (pid == 0) {
86 		ATF_REQUIRE(dup2(filedes[1], STDERR_FILENO) != -1);
87 		ATF_REQUIRE(close(filedes[0]) == 0);
88 		ATF_REQUIRE(close(filedes[1]) == 0);
89 
90 		(*fun)();
91 	}
92 
93 	ATF_REQUIRE(close(filedes[1]) == 0);
94 
95 	fp = fdopen(filedes[0], "r");
96 	ATF_REQUIRE(fp != NULL);
97 
98 	buffer = fgetln(fp, &len);
99 	ATF_REQUIRE(buffer != 0);
100 	ATF_REQUIRE(!ferror(fp));
101 	ATF_REQUIRE(strstr(buffer, string) != NULL);
102 	ATF_REQUIRE(wait(&status) == pid);
103 	ATF_REQUIRE(!WIFEXITED(status));
104 	ATF_REQUIRE(WIFSIGNALED(status));
105 	ATF_REQUIRE(!WIFSTOPPED(status));
106 	ATF_REQUIRE(!WIFCONTINUED(status));
107 }
108 
109 UBSAN_TC(add_overflow_signed);
UBSAN_TC_HEAD(add_overflow_signed,tc)110 UBSAN_TC_HEAD(add_overflow_signed, tc)
111 {
112         UBSAN_MD_VAR(tc, "descr",
113 	    "Checks -fsanitize=signed-integer-overflow");
114 }
115 
116 static void
test_add_overflow_signed(void)117 test_add_overflow_signed(void)
118 {
119 	volatile int a = INT_MAX;
120 	volatile int b = atoi("1");
121 
122 	raise((a + b) ? SIGSEGV : SIGBUS);
123 }
124 
UBSAN_TC_BODY(add_overflow_signed,tc)125 UBSAN_TC_BODY(add_overflow_signed, tc)
126 {
127 
128 	test_case(test_add_overflow_signed, " signed integer overflow: ");
129 }
130 
131 #ifdef __clang__
132 UBSAN_TC(add_overflow_unsigned);
UBSAN_TC_HEAD(add_overflow_unsigned,tc)133 UBSAN_TC_HEAD(add_overflow_unsigned, tc)
134 {
135         UBSAN_MD_VAR(tc, "descr",
136 	    "Checks -fsanitize=unsigned-integer-overflow");
137 }
138 
139 static void
test_add_overflow_unsigned(void)140 test_add_overflow_unsigned(void)
141 {
142 	volatile unsigned int a = UINT_MAX;
143 	volatile unsigned int b = atoi("1");
144 
145 	raise((a + b) ? SIGSEGV : SIGBUS);
146 }
147 
UBSAN_TC_BODY(add_overflow_unsigned,tc)148 UBSAN_TC_BODY(add_overflow_unsigned, tc)
149 {
150 
151 	test_case(test_add_overflow_unsigned, " unsigned integer overflow: ");
152 }
153 #endif
154 
155 UBSAN_TC(builtin_unreachable);
UBSAN_TC_HEAD(builtin_unreachable,tc)156 UBSAN_TC_HEAD(builtin_unreachable, tc)
157 {
158         UBSAN_MD_VAR(tc, "descr",
159 	    "Checks -fsanitize=unreachable");
160 }
161 
162 static void
test_builtin_unreachable(void)163 test_builtin_unreachable(void)
164 {
165 	volatile int a = atoi("1");
166 	volatile int b = atoi("1");
167 
168 	if (a == b) {
169 		__builtin_unreachable();
170 	}
171 	// This shall not be reached
172 	raise(SIGSEGV);
173 }
174 
UBSAN_TC_BODY(builtin_unreachable,tc)175 UBSAN_TC_BODY(builtin_unreachable, tc)
176 {
177 
178 	test_case(test_builtin_unreachable, " calling __builtin_unreachable()");
179 }
180 
181 UBSAN_TC(divrem_overflow_signed_div);
UBSAN_TC_HEAD(divrem_overflow_signed_div,tc)182 UBSAN_TC_HEAD(divrem_overflow_signed_div, tc)
183 {
184         UBSAN_MD_VAR(tc, "descr",
185 	    "Checks -fsanitize=signed-integer-overflow");
186 }
187 
188 static void
test_divrem_overflow_signed_div(void)189 test_divrem_overflow_signed_div(void)
190 {
191 	volatile int a = INT_MIN;
192 	volatile int b = atoi("-1");
193 
194 	raise((a / b) ? SIGSEGV : SIGBUS); // SIGFPE will be triggered before exiting
195 }
196 
UBSAN_TC_BODY(divrem_overflow_signed_div,tc)197 UBSAN_TC_BODY(divrem_overflow_signed_div, tc)
198 {
199 
200 	test_case(test_divrem_overflow_signed_div, " signed integer overflow: ");
201 }
202 
203 UBSAN_TC(divrem_overflow_signed_mod);
UBSAN_TC_HEAD(divrem_overflow_signed_mod,tc)204 UBSAN_TC_HEAD(divrem_overflow_signed_mod, tc)
205 {
206         UBSAN_MD_VAR(tc, "descr",
207 	    "Checks -fsanitize=signed-integer-overflow");
208 }
209 
210 static void
test_divrem_overflow_signed_mod(void)211 test_divrem_overflow_signed_mod(void)
212 {
213 	volatile int a = INT_MIN;
214 	volatile int b = atoi("-1");
215 
216 	raise((a % b) ? SIGSEGV : SIGBUS);
217 }
218 
UBSAN_TC_BODY(divrem_overflow_signed_mod,tc)219 UBSAN_TC_BODY(divrem_overflow_signed_mod, tc)
220 {
221 
222 	test_case(test_divrem_overflow_signed_mod, " signed integer overflow: ");
223 }
224 
225 #if defined(__cplusplus) && defined(__clang__) && defined(__x86_64__)
226 UBSAN_TC(function_type_mismatch);
UBSAN_TC_HEAD(function_type_mismatch,tc)227 UBSAN_TC_HEAD(function_type_mismatch, tc)
228 {
229         UBSAN_MD_VAR(tc, "descr",
230 	    "Checks -fsanitize=function");
231 }
232 
233 static int
fun_type_mismatch(void)234 fun_type_mismatch(void)
235 {
236 
237 	return 0;
238 }
239 
240 static void
test_function_type_mismatch(void)241 test_function_type_mismatch(void)
242 {
243 
244 	raise(reinterpret_cast<int(*)(int)>
245 	    (reinterpret_cast<uintptr_t>(fun_type_mismatch))(1) ? SIGSEGV : SIGBUS);
246 }
247 
UBSAN_TC_BODY(function_type_mismatch,tc)248 UBSAN_TC_BODY(function_type_mismatch, tc)
249 {
250 
251 	test_case(test_function_type_mismatch, " call to function ");
252 }
253 #endif
254 
255 #ifdef __clang__
256 #define INVALID_BUILTIN(type)				\
257 UBSAN_TC(invalid_builtin_##type);			\
258 UBSAN_TC_HEAD(invalid_builtin_##type, tc)		\
259 {							\
260         UBSAN_MD_VAR(tc, "descr",			\
261 	    "Checks -fsanitize=builtin");		\
262 }							\
263 							\
264 static void						\
265 test_invalid_builtin_##type(void)			\
266 {							\
267 							\
268 	volatile int a = atoi("0");			\
269 	volatile int b = __builtin_##type(a);		\
270 	raise(b ? SIGBUS : SIGSEGV);			\
271 }							\
272 							\
273 UBSAN_TC_BODY(invalid_builtin_##type, tc)		\
274 {							\
275 							\
276 	test_case(test_invalid_builtin_##type,		\
277 	          " passing zero to ");			\
278 }
279 
280 INVALID_BUILTIN(ctz)
281 INVALID_BUILTIN(ctzl)
282 INVALID_BUILTIN(ctzll)
283 INVALID_BUILTIN(clz)
284 INVALID_BUILTIN(clzl)
285 INVALID_BUILTIN(clzll)
286 #endif
287 
288 UBSAN_TC(load_invalid_value_bool);
UBSAN_TC_HEAD(load_invalid_value_bool,tc)289 UBSAN_TC_HEAD(load_invalid_value_bool, tc)
290 {
291         UBSAN_MD_VAR(tc, "descr",
292 	    "Checks -fsanitize=bool");
293 }
294 
295 static void
test_load_invalid_value_bool(void)296 test_load_invalid_value_bool(void)
297 {
298 	volatile int a = INT_MAX - atoi("10");
299 	volatile bool b = *(REINTERPRET_CAST(volatile bool *, &a));
300 
301 	raise(b ? SIGSEGV : SIGBUS);
302 }
303 
UBSAN_TC_BODY(load_invalid_value_bool,tc)304 UBSAN_TC_BODY(load_invalid_value_bool, tc)
305 {
306 	test_case(test_load_invalid_value_bool, " load of value ");
307 }
308 
309 #if defined(__cplusplus) // ? && (defined(__x86_64__) || defined(__i386__))
310 UBSAN_TC(load_invalid_value_enum);
UBSAN_TC_HEAD(load_invalid_value_enum,tc)311 UBSAN_TC_HEAD(load_invalid_value_enum, tc)
312 {
313         UBSAN_MD_VAR(tc, "descr",
314 	    "Checks -fsanitize=enum");
315 }
316 
317 static void
test_load_invalid_value_enum(void)318 test_load_invalid_value_enum(void)
319 {
320 	enum e { e1, e2, e3, e4 };
321 	volatile int a = INT_MAX - atoi("10");
322 	volatile enum e E = *(REINTERPRET_CAST(volatile enum e*, &a));
323 
324 	raise((E == e1) ? SIGSEGV : SIGBUS);
325 }
326 
UBSAN_TC_BODY(load_invalid_value_enum,tc)327 UBSAN_TC_BODY(load_invalid_value_enum, tc)
328 {
329 
330 	test_case(test_load_invalid_value_enum, " load of value ");
331 }
332 #endif
333 
334 #ifdef __cplusplus
335 UBSAN_TC(missing_return);
UBSAN_TC_HEAD(missing_return,tc)336 UBSAN_TC_HEAD(missing_return, tc)
337 {
338         UBSAN_MD_VAR(tc, "descr",
339 	    "Checks -fsanitize=return");
340 }
341 
342 static int
fun_missing_return(void)343 fun_missing_return(void)
344 {
345 }
346 
347 static void
test_missing_return(void)348 test_missing_return(void)
349 {
350 	volatile int a = fun_missing_return();
351 
352 	// This interceptor shall be fatal, however if it won't generate
353 	// a signal, do it on our own here:
354 	raise(a ? SIGSEGV : SIGBUS);
355 }
356 
UBSAN_TC_BODY(missing_return,tc)357 UBSAN_TC_BODY(missing_return, tc)
358 {
359 
360 	test_case(test_missing_return,
361 	          " execution reached the end of a value-returning function "
362 	          "without returning a value");
363 }
364 #endif
365 
366 UBSAN_TC(mul_overflow_signed);
UBSAN_TC_HEAD(mul_overflow_signed,tc)367 UBSAN_TC_HEAD(mul_overflow_signed, tc)
368 {
369         UBSAN_MD_VAR(tc, "descr",
370 	    "Checks -fsanitize=signed-integer-overflow");
371 }
372 
373 static void
test_mul_overflow_signed(void)374 test_mul_overflow_signed(void)
375 {
376 	volatile int a = INT_MAX;
377 	volatile int b = atoi("2");
378 
379 	raise((a * b) ? SIGSEGV : SIGBUS);
380 }
381 
UBSAN_TC_BODY(mul_overflow_signed,tc)382 UBSAN_TC_BODY(mul_overflow_signed, tc)
383 {
384 
385 	test_case(test_mul_overflow_signed, " signed integer overflow: ");
386 }
387 
388 #ifdef __clang__
389 UBSAN_TC(mul_overflow_unsigned);
UBSAN_TC_HEAD(mul_overflow_unsigned,tc)390 UBSAN_TC_HEAD(mul_overflow_unsigned, tc)
391 {
392         UBSAN_MD_VAR(tc, "descr",
393 	    "Checks -fsanitize=unsigned-integer-overflow");
394 }
395 
396 static void
test_mul_overflow_unsigned(void)397 test_mul_overflow_unsigned(void)
398 {
399 	volatile unsigned int a = UINT_MAX;
400 	volatile unsigned int b = atoi("2");
401 
402 	raise((a * b) ? SIGSEGV : SIGBUS);
403 }
404 
UBSAN_TC_BODY(mul_overflow_unsigned,tc)405 UBSAN_TC_BODY(mul_overflow_unsigned, tc)
406 {
407 
408 	test_case(test_mul_overflow_unsigned, " unsigned integer overflow: ");
409 }
410 #endif
411 
412 #ifdef __clang__
413 UBSAN_TC(negate_overflow_signed);
UBSAN_TC_HEAD(negate_overflow_signed,tc)414 UBSAN_TC_HEAD(negate_overflow_signed, tc)
415 {
416         UBSAN_MD_VAR(tc, "descr",
417 	    "Checks -fsanitize=signed-integer-overflow");
418 }
419 
420 static void
test_negate_overflow_signed(void)421 test_negate_overflow_signed(void)
422 {
423 	volatile int a = INT_MIN;
424 
425 	raise(-a ? SIGSEGV : SIGBUS);
426 }
427 
UBSAN_TC_BODY(negate_overflow_signed,tc)428 UBSAN_TC_BODY(negate_overflow_signed, tc)
429 {
430 
431 	test_case(test_negate_overflow_signed, " negation of ");
432 }
433 
434 UBSAN_TC(negate_overflow_unsigned);
UBSAN_TC_HEAD(negate_overflow_unsigned,tc)435 UBSAN_TC_HEAD(negate_overflow_unsigned, tc)
436 {
437         UBSAN_MD_VAR(tc, "descr",
438 	    "Checks -fsanitize=unsigned-integer-overflow");
439 }
440 
441 static void
test_negate_overflow_unsigned(void)442 test_negate_overflow_unsigned(void)
443 {
444 	volatile unsigned int a = UINT_MAX;
445 
446 	raise(-a ? SIGSEGV : SIGBUS);
447 }
448 
UBSAN_TC_BODY(negate_overflow_unsigned,tc)449 UBSAN_TC_BODY(negate_overflow_unsigned, tc)
450 {
451 
452 	test_case(test_negate_overflow_unsigned, " negation of ");
453 }
454 #endif
455 
456 #ifdef __clang__
457 UBSAN_TC(nonnull_arg);
UBSAN_TC_HEAD(nonnull_arg,tc)458 UBSAN_TC_HEAD(nonnull_arg, tc)
459 {
460         UBSAN_MD_VAR(tc, "descr",
461 	    "Checks -fsanitize=nullability-arg");
462 }
463 
464 static void *
fun_nonnull_arg(void * _Nonnull ptr)465 fun_nonnull_arg(void * _Nonnull ptr)
466 {
467 
468 	return ptr;
469 }
470 
471 static void
test_nonnull_arg(void)472 test_nonnull_arg(void)
473 {
474 	volatile intptr_t a = atoi("0");
475 
476 	raise(fun_nonnull_arg(REINTERPRET_CAST(void *, a)) ? SIGSEGV : SIGBUS);
477 }
478 
UBSAN_TC_BODY(nonnull_arg,tc)479 UBSAN_TC_BODY(nonnull_arg, tc)
480 {
481 
482 	test_case(test_nonnull_arg, " null pointer passed as argument ");
483 }
484 
485 UBSAN_TC(nonnull_assign);
UBSAN_TC_HEAD(nonnull_assign,tc)486 UBSAN_TC_HEAD(nonnull_assign, tc)
487 {
488         UBSAN_MD_VAR(tc, "descr",
489 	    "Checks -fsanitize=nullability-assign");
490 }
491 
492 static volatile void * _Nonnull
fun_nonnull_assign(intptr_t a)493 fun_nonnull_assign(intptr_t a)
494 {
495 	volatile void *_Nonnull ptr;
496 
497 	ptr = REINTERPRET_CAST(void *, a);
498 
499 	return ptr;
500 }
501 
502 static void
test_nonnull_assign(void)503 test_nonnull_assign(void)
504 {
505 	volatile intptr_t a = atoi("0");
506 
507 	raise(fun_nonnull_assign(a) ? SIGSEGV : SIGBUS);
508 }
509 
UBSAN_TC_BODY(nonnull_assign,tc)510 UBSAN_TC_BODY(nonnull_assign, tc)
511 {
512 
513 	test_case(test_nonnull_assign, " _Nonnull binding to null pointer of type ");
514 }
515 
516 UBSAN_TC(nonnull_return);
UBSAN_TC_HEAD(nonnull_return,tc)517 UBSAN_TC_HEAD(nonnull_return, tc)
518 {
519         UBSAN_MD_VAR(tc, "descr",
520 	    "Checks -fsanitize=nullability-return");
521 }
522 
523 static void * _Nonnull
fun_nonnull_return(void)524 fun_nonnull_return(void)
525 {
526 	volatile intptr_t a = atoi("0");
527 
528 	return REINTERPRET_CAST(void *, a);
529 }
530 
531 static void
test_nonnull_return(void)532 test_nonnull_return(void)
533 {
534 
535 	raise(fun_nonnull_return() ? SIGSEGV : SIGBUS);
536 }
537 
UBSAN_TC_BODY(nonnull_return,tc)538 UBSAN_TC_BODY(nonnull_return, tc)
539 {
540 
541 	test_case(test_nonnull_return, " null pointer returned from function ");
542 }
543 #endif
544 
545 UBSAN_TC(out_of_bounds);
UBSAN_TC_HEAD(out_of_bounds,tc)546 UBSAN_TC_HEAD(out_of_bounds, tc)
547 {
548         UBSAN_MD_VAR(tc, "descr",
549 	    "Checks -fsanitize=bounds");
550 }
551 
552 static void
test_out_of_bounds(void)553 test_out_of_bounds(void)
554 {
555 	int A[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
556 	volatile int a = atoi("10");
557 
558 	raise(A[a] ? SIGSEGV : SIGBUS);
559 }
560 
UBSAN_TC_BODY(out_of_bounds,tc)561 UBSAN_TC_BODY(out_of_bounds, tc)
562 {
563 
564 	test_case(test_out_of_bounds, " index 10 is out of range for type ");
565 }
566 
567 #ifdef __clang__
568 UBSAN_TC(pointer_overflow);
UBSAN_TC_HEAD(pointer_overflow,tc)569 UBSAN_TC_HEAD(pointer_overflow, tc)
570 {
571         UBSAN_MD_VAR(tc, "descr",
572 	    "Checks -fsanitize=pointer-overflow");
573 }
574 
575 static void
test_pointer_overflow(void)576 test_pointer_overflow(void)
577 {
578 	volatile uintptr_t a = UINTPTR_MAX;
579 	volatile uintptr_t b = atoi("1");
580 	volatile int *ptr = REINTERPRET_CAST(int *, a);
581 
582 	raise((ptr + b) ? SIGSEGV : SIGBUS);
583 }
584 
UBSAN_TC_BODY(pointer_overflow,tc)585 UBSAN_TC_BODY(pointer_overflow, tc)
586 {
587 
588 	test_case(test_pointer_overflow, " pointer expression with base ");
589 }
590 #endif
591 
592 #ifndef __cplusplus
593 UBSAN_TC(shift_out_of_bounds_signednessbit);
UBSAN_TC_HEAD(shift_out_of_bounds_signednessbit,tc)594 UBSAN_TC_HEAD(shift_out_of_bounds_signednessbit, tc)
595 {
596         UBSAN_MD_VAR(tc, "descr",
597 	    "Checks -fsanitize=shift");
598 }
599 
600 static void
test_shift_out_of_bounds_signednessbit(void)601 test_shift_out_of_bounds_signednessbit(void)
602 {
603 	volatile int32_t a = atoi("1");
604 
605 	raise((a << 31) != 0 ? SIGSEGV : SIGBUS);
606 }
607 
UBSAN_TC_BODY(shift_out_of_bounds_signednessbit,tc)608 UBSAN_TC_BODY(shift_out_of_bounds_signednessbit, tc)
609 {
610 
611 	test_case(test_shift_out_of_bounds_signednessbit, " left shift of ");
612 }
613 #endif
614 
615 UBSAN_TC(shift_out_of_bounds_signedoverflow);
UBSAN_TC_HEAD(shift_out_of_bounds_signedoverflow,tc)616 UBSAN_TC_HEAD(shift_out_of_bounds_signedoverflow, tc)
617 {
618         UBSAN_MD_VAR(tc, "descr",
619 	    "Checks -fsanitize=shift");
620 }
621 
622 static void
test_shift_out_of_bounds_signedoverflow(void)623 test_shift_out_of_bounds_signedoverflow(void)
624 {
625 	volatile int32_t a = atoi("1");
626 	volatile int32_t b = atoi("30");
627 	a <<= b;
628 
629 	raise((a << 10) != 0 ? SIGSEGV : SIGBUS);
630 }
631 
UBSAN_TC_BODY(shift_out_of_bounds_signedoverflow,tc)632 UBSAN_TC_BODY(shift_out_of_bounds_signedoverflow, tc)
633 {
634 
635 	test_case(test_shift_out_of_bounds_signedoverflow, " left shift of ");
636 }
637 
638 UBSAN_TC(shift_out_of_bounds_negativeexponent);
UBSAN_TC_HEAD(shift_out_of_bounds_negativeexponent,tc)639 UBSAN_TC_HEAD(shift_out_of_bounds_negativeexponent, tc)
640 {
641         UBSAN_MD_VAR(tc, "descr",
642 	    "Checks -fsanitize=shift");
643 }
644 
645 static void
test_shift_out_of_bounds_negativeexponent(void)646 test_shift_out_of_bounds_negativeexponent(void)
647 {
648 	volatile int32_t a = atoi("1");
649 	volatile int32_t b = atoi("-10");
650 
651 	raise((a << b) != 0 ? SIGSEGV : SIGBUS);
652 }
653 
UBSAN_TC_BODY(shift_out_of_bounds_negativeexponent,tc)654 UBSAN_TC_BODY(shift_out_of_bounds_negativeexponent, tc)
655 {
656 
657 	test_case(test_shift_out_of_bounds_negativeexponent, " shift exponent -");
658 }
659 
660 UBSAN_TC(shift_out_of_bounds_toolargeexponent);
UBSAN_TC_HEAD(shift_out_of_bounds_toolargeexponent,tc)661 UBSAN_TC_HEAD(shift_out_of_bounds_toolargeexponent, tc)
662 {
663         UBSAN_MD_VAR(tc, "descr",
664 	    "Checks -fsanitize=shift");
665 }
666 
667 static void
test_shift_out_of_bounds_toolargeexponent(void)668 test_shift_out_of_bounds_toolargeexponent(void)
669 {
670 	volatile int32_t a = atoi("1");
671 	volatile int32_t b = atoi("40");
672 
673 	raise((a << b) != 0 ? SIGSEGV : SIGBUS);
674 }
675 
UBSAN_TC_BODY(shift_out_of_bounds_toolargeexponent,tc)676 UBSAN_TC_BODY(shift_out_of_bounds_toolargeexponent, tc)
677 {
678 
679 	test_case(test_shift_out_of_bounds_toolargeexponent, " shift exponent ");
680 }
681 
682 #ifdef __clang__
683 UBSAN_TC(sub_overflow_signed);
UBSAN_TC_HEAD(sub_overflow_signed,tc)684 UBSAN_TC_HEAD(sub_overflow_signed, tc)
685 {
686         UBSAN_MD_VAR(tc, "descr",
687 	    "Checks -fsanitize=signed-integer-overflow");
688 }
689 
690 static void
test_sub_overflow_signed(void)691 test_sub_overflow_signed(void)
692 {
693 	volatile int a = INT_MIN;
694 	volatile int b = atoi("1");
695 
696 	raise((a - b) ? SIGSEGV : SIGBUS);
697 }
698 
UBSAN_TC_BODY(sub_overflow_signed,tc)699 UBSAN_TC_BODY(sub_overflow_signed, tc)
700 {
701 
702 	test_case(test_sub_overflow_signed, " signed integer overflow: ");
703 }
704 
705 UBSAN_TC(sub_overflow_unsigned);
UBSAN_TC_HEAD(sub_overflow_unsigned,tc)706 UBSAN_TC_HEAD(sub_overflow_unsigned, tc)
707 {
708         UBSAN_MD_VAR(tc, "descr",
709 	    "Checks -fsanitize=unsigned-integer-overflow");
710 }
711 
712 static void
test_sub_overflow_unsigned(void)713 test_sub_overflow_unsigned(void)
714 {
715 	volatile unsigned int a = atoi("0");
716 	volatile unsigned int b = atoi("1");
717 
718 	raise((a - b) ? SIGSEGV : SIGBUS);
719 }
720 
UBSAN_TC_BODY(sub_overflow_unsigned,tc)721 UBSAN_TC_BODY(sub_overflow_unsigned, tc)
722 {
723 
724 	test_case(test_sub_overflow_unsigned, " unsigned integer overflow: ");
725 }
726 #endif
727 
728 #ifndef __clang__
729 // The Clang/LLVM code generation does not catch every misaligned access
730 UBSAN_TC(type_mismatch_misaligned);
UBSAN_TC_HEAD(type_mismatch_misaligned,tc)731 UBSAN_TC_HEAD(type_mismatch_misaligned, tc)
732 {
733         UBSAN_MD_VAR(tc, "descr",
734 	    "Checks -fsanitize=alignment");
735 }
736 
737 static void
test_type_mismatch_misaligned(void)738 test_type_mismatch_misaligned(void)
739 {
740 	volatile int8_t A[10] __aligned(4);
741 	volatile int *b;
742 
743 	memset(__UNVOLATILE(A), 0, sizeof(A));
744 	b = REINTERPRET_CAST(volatile int *, &A[1]);
745 
746 	raise((*b) ? SIGSEGV : SIGBUS);
747 }
748 
UBSAN_TC_BODY(type_mismatch_misaligned,tc)749 UBSAN_TC_BODY(type_mismatch_misaligned, tc)
750 {
751 
752 	test_case(test_type_mismatch_misaligned, " load of misaligned address ");
753 }
754 #endif
755 
756 UBSAN_TC(vla_bound_not_positive);
UBSAN_TC_HEAD(vla_bound_not_positive,tc)757 UBSAN_TC_HEAD(vla_bound_not_positive, tc)
758 {
759         UBSAN_MD_VAR(tc, "descr",
760 	    "Checks -fsanitize=vla-bound");
761 }
762 
763 static void
test_vla_bound_not_positive(void)764 test_vla_bound_not_positive(void)
765 {
766 	volatile int a = atoi("-1");
767 	int A[a];
768 
769 	raise(A[0] ? SIGBUS : SIGSEGV);
770 }
771 
UBSAN_TC_BODY(vla_bound_not_positive,tc)772 UBSAN_TC_BODY(vla_bound_not_positive, tc)
773 {
774 
775 	test_case(test_vla_bound_not_positive, " variable length array bound value ");
776 }
777 
778 UBSAN_TC(integer_divide_by_zero);
UBSAN_TC_HEAD(integer_divide_by_zero,tc)779 UBSAN_TC_HEAD(integer_divide_by_zero, tc)
780 {
781         UBSAN_MD_VAR(tc, "descr",
782 	    "Checks -fsanitize=integer-divide-by-zero");
783 }
784 
785 static void
test_integer_divide_by_zero(void)786 test_integer_divide_by_zero(void)
787 {
788 	volatile int a = atoi("-1");
789 	volatile int b = atoi("0");
790 
791 	raise((a / b) ? SIGSEGV : SIGBUS);
792 }
793 
UBSAN_TC_BODY(integer_divide_by_zero,tc)794 UBSAN_TC_BODY(integer_divide_by_zero, tc)
795 {
796 
797 	test_case(test_integer_divide_by_zero, " signed integer overflow: ");
798 }
799 
800 #ifdef __clang__
801 UBSAN_TC(float_divide_by_zero);
UBSAN_TC_HEAD(float_divide_by_zero,tc)802 UBSAN_TC_HEAD(float_divide_by_zero, tc)
803 {
804         UBSAN_MD_VAR(tc, "descr",
805 	    "Checks -fsanitize=float-divide-by-zero");
806 }
807 
808 static void
test_float_divide_by_zero(void)809 test_float_divide_by_zero(void)
810 {
811 	volatile float a = strtof("1.5", NULL);
812 	volatile float b = strtof("0.0", NULL);
813 
814 	raise((a / b) > 0 ? SIGSEGV : SIGBUS);
815 }
816 
UBSAN_TC_BODY(float_divide_by_zero,tc)817 UBSAN_TC_BODY(float_divide_by_zero, tc)
818 {
819 
820 	test_case(test_float_divide_by_zero, " unsigned integer overflow: ");
821 }
822 #endif
823 
824 #else
825 UBSAN_TC(dummy);
UBSAN_TC_HEAD(dummy,tc)826 UBSAN_TC_HEAD(dummy, tc)
827 {
828         UBSAN_MD_VAR(tc, "descr",
829 	    "A dummy test");
830 }
831 
UBSAN_TC_BODY(dummy,tc)832 UBSAN_TC_BODY(dummy, tc)
833 {
834 
835 	// Dummy, skipped
836 	// The ATF framework requires at least a single defined test.
837 }
838 #endif
839 
UBSAN_CASES(tp)840 UBSAN_CASES(tp)
841 {
842 #ifdef ENABLE_TESTS
843 	UBSAN_TEST_CASE(tp, add_overflow_signed);
844 #ifdef __clang__
845 	UBSAN_TEST_CASE(tp, add_overflow_unsigned);
846 #endif
847 	UBSAN_TEST_CASE(tp, builtin_unreachable);
848 //	UBSAN_TEST_CASE(tp, cfi_bad_type);	// TODO
849 //	UBSAN_TEST_CASE(tp, cfi_check_fail);	// TODO
850 	UBSAN_TEST_CASE(tp, divrem_overflow_signed_div);
851 	UBSAN_TEST_CASE(tp, divrem_overflow_signed_mod);
852 //	UBSAN_TEST_CASE(tp, dynamic_type_cache_miss); // Not supported in uUBSan
853 //	UBSAN_TEST_CASE(tp, float_cast_overflow);	// TODO
854 #if defined(__cplusplus) && defined(__clang__) && defined(__x86_64__)
855 	UBSAN_TEST_CASE(tp, function_type_mismatch);
856 #endif
857 #ifdef __clang__
858 	UBSAN_TEST_CASE(tp, invalid_builtin_ctz);
859 	UBSAN_TEST_CASE(tp, invalid_builtin_ctzl);
860 	UBSAN_TEST_CASE(tp, invalid_builtin_ctzll);
861 	UBSAN_TEST_CASE(tp, invalid_builtin_clz);
862 	UBSAN_TEST_CASE(tp, invalid_builtin_clzl);
863 	UBSAN_TEST_CASE(tp, invalid_builtin_clzll);
864 #endif
865 	UBSAN_TEST_CASE(tp, load_invalid_value_bool);
866 #ifdef __cplusplus // ? && (defined(__x86_64__) || defined(__i386__))
867 	UBSAN_TEST_CASE(tp, load_invalid_value_enum);
868 #endif
869 #ifdef __cplusplus
870 	UBSAN_TEST_CASE(tp, missing_return);
871 #endif
872 	UBSAN_TEST_CASE(tp, mul_overflow_signed);
873 #ifdef __clang__
874 	UBSAN_TEST_CASE(tp, mul_overflow_unsigned);
875 	UBSAN_TEST_CASE(tp, negate_overflow_signed);
876 	UBSAN_TEST_CASE(tp, negate_overflow_unsigned);
877 	// Clang/LLVM specific extension
878 	// http://clang.llvm.org/docs/AttributeReference.html#nullability-attributes
879 	UBSAN_TEST_CASE(tp, nonnull_arg);
880 	UBSAN_TEST_CASE(tp, nonnull_assign);
881 	UBSAN_TEST_CASE(tp, nonnull_return);
882 #endif
883 	UBSAN_TEST_CASE(tp, out_of_bounds);
884 #ifdef __clang__
885 	UBSAN_TEST_CASE(tp, pointer_overflow);
886 #endif
887 #ifndef __cplusplus
888 	// Acceptable in C++11
889 	UBSAN_TEST_CASE(tp, shift_out_of_bounds_signednessbit);
890 #endif
891 	UBSAN_TEST_CASE(tp, shift_out_of_bounds_signedoverflow);
892 	UBSAN_TEST_CASE(tp, shift_out_of_bounds_negativeexponent);
893 	UBSAN_TEST_CASE(tp, shift_out_of_bounds_toolargeexponent);
894 #ifdef __clang__
895 	UBSAN_TEST_CASE(tp, sub_overflow_signed);
896 	UBSAN_TEST_CASE(tp, sub_overflow_unsigned);
897 #endif
898 #ifndef __clang__
899 	UBSAN_TEST_CASE(tp, type_mismatch_misaligned);
900 #endif
901 	UBSAN_TEST_CASE(tp, vla_bound_not_positive);
902 	UBSAN_TEST_CASE(tp, integer_divide_by_zero);
903 #ifdef __clang__
904 	UBSAN_TEST_CASE(tp, float_divide_by_zero);
905 #endif
906 #else
907 	UBSAN_TEST_CASE(tp, dummy);
908 #endif
909 
910 #ifndef __cplusplus
911 	return atf_no_error();
912 #endif
913 }
914