1 /* $NetBSD: t_ubsan.c,v 1.1 2018/08/03 04:18:40 kamil 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.1 2018/08/03 04:18:40 kamil 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 = 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 = 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) ? 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) ? 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) ? 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) ? 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