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