Home | History | Annotate | Line # | Download | only in misc
      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
     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);
    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
    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 
    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);
    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
    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 
    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);
    156 UBSAN_TC_HEAD(builtin_unreachable, tc)
    157 {
    158         UBSAN_MD_VAR(tc, "descr",
    159 	    "Checks -fsanitize=unreachable");
    160 }
    161 
    162 static 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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    227 UBSAN_TC_HEAD(function_type_mismatch, tc)
    228 {
    229         UBSAN_MD_VAR(tc, "descr",
    230 	    "Checks -fsanitize=function");
    231 }
    232 
    233 static int
    234 fun_type_mismatch(void)
    235 {
    236 
    237 	return 0;
    238 }
    239 
    240 static 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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    336 UBSAN_TC_HEAD(missing_return, tc)
    337 {
    338         UBSAN_MD_VAR(tc, "descr",
    339 	    "Checks -fsanitize=return");
    340 }
    341 
    342 static int
    343 fun_missing_return(void)
    344 {
    345 }
    346 
    347 static 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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    421 test_negate_overflow_signed(void)
    422 {
    423 	volatile int a = INT_MIN;
    424 
    425 	raise(-a ? SIGSEGV : SIGBUS);
    426 }
    427 
    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);
    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
    442 test_negate_overflow_unsigned(void)
    443 {
    444 	volatile unsigned int a = UINT_MAX;
    445 
    446 	raise(-a ? SIGSEGV : SIGBUS);
    447 }
    448 
    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);
    458 UBSAN_TC_HEAD(nonnull_arg, tc)
    459 {
    460         UBSAN_MD_VAR(tc, "descr",
    461 	    "Checks -fsanitize=nullability-arg");
    462 }
    463 
    464 static void *
    465 fun_nonnull_arg(void * _Nonnull ptr)
    466 {
    467 
    468 	return ptr;
    469 }
    470 
    471 static 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 
    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);
    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
    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
    503 test_nonnull_assign(void)
    504 {
    505 	volatile intptr_t a = atoi("0");
    506 
    507 	raise(fun_nonnull_assign(a) ? SIGSEGV : SIGBUS);
    508 }
    509 
    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);
    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
    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
    532 test_nonnull_return(void)
    533 {
    534 
    535 	raise(fun_nonnull_return() ? SIGSEGV : SIGBUS);
    536 }
    537 
    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);
    546 UBSAN_TC_HEAD(out_of_bounds, tc)
    547 {
    548         UBSAN_MD_VAR(tc, "descr",
    549 	    "Checks -fsanitize=bounds");
    550 }
    551 
    552 static 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 
    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);
    569 UBSAN_TC_HEAD(pointer_overflow, tc)
    570 {
    571         UBSAN_MD_VAR(tc, "descr",
    572 	    "Checks -fsanitize=pointer-overflow");
    573 }
    574 
    575 static 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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    731 UBSAN_TC_HEAD(type_mismatch_misaligned, tc)
    732 {
    733         UBSAN_MD_VAR(tc, "descr",
    734 	    "Checks -fsanitize=alignment");
    735 }
    736 
    737 static 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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    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
    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 
    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);
    826 UBSAN_TC_HEAD(dummy, tc)
    827 {
    828         UBSAN_MD_VAR(tc, "descr",
    829 	    "A dummy test");
    830 }
    831 
    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 
    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