diff options
Diffstat (limited to 'lib/ubsan')
47 files changed, 345 insertions, 261 deletions
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt index c8470bc6d3536..675c47f6a65eb 100644 --- a/lib/ubsan/CMakeLists.txt +++ b/lib/ubsan/CMakeLists.txt @@ -34,17 +34,22 @@ else() # Main UBSan runtime. add_compiler_rt_static_runtime(clang_rt.ubsan-${arch} ${arch} SOURCES ${UBSAN_SOURCES} - CFLAGS ${UBSAN_CFLAGS} - SYMS ubsan.syms) + CFLAGS ${UBSAN_CFLAGS}) # C++-specific parts of UBSan runtime. Requires a C++ ABI library. add_compiler_rt_static_runtime(clang_rt.ubsan_cxx-${arch} ${arch} SOURCES ${UBSAN_CXX_SOURCES} - CFLAGS ${UBSAN_CFLAGS} - SYMS ubsan.syms) + CFLAGS ${UBSAN_CFLAGS}) list(APPEND UBSAN_RUNTIME_LIBRARIES - clang_rt.san-${arch} - clang_rt.ubsan-${arch} - clang_rt.ubsan_cxx-${arch}) + clang_rt.san-${arch} + clang_rt.ubsan-${arch} + clang_rt.ubsan_cxx-${arch}) + if (UNIX AND NOT ${arch} STREQUAL "i386") + add_sanitizer_rt_symbols(clang_rt.ubsan-${arch} ubsan.syms.extra) + add_sanitizer_rt_symbols(clang_rt.ubsan_cxx-${arch} ubsan.syms.extra) + list(APPEND UBSAN_RUNTIME_LIBRARIES + clang_rt.ubsan-${arch}-symbols + clang_rt.ubsan_cxx-${arch}-symbols) + endif() endforeach() endif() diff --git a/lib/ubsan/lit_tests/AsanConfig/lit.cfg b/lib/ubsan/lit_tests/AsanConfig/lit.cfg new file mode 100644 index 0000000000000..407e5ec32e60b --- /dev/null +++ b/lib/ubsan/lit_tests/AsanConfig/lit.cfg @@ -0,0 +1,25 @@ +# -*- Python -*- + +import os + +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if not attr_value: + lit_config.fatal( + "No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg " % attr_name) + return attr_value + +ubsan_lit_tests_dir = get_required_attr(config, "ubsan_lit_tests_dir") +ubsan_lit_cfg = os.path.join(ubsan_lit_tests_dir, "lit.common.cfg") +lit_config.load_config(config, ubsan_lit_cfg) + +config.name = 'UndefinedBehaviorSanitizer-AddressSanitizer' + +# Define %clang and %clangxx substitutions to use in test RUN lines. +config.substitutions.append( ("%clang ", (" " + config.clang + + " -fsanitize=address ")) ) +config.substitutions.append( ("%clangxx ", (" " + config.clang + + " -fsanitize=address" + + " --driver-mode=g++ ")) ) diff --git a/lib/ubsan/lit_tests/AsanConfig/lit.site.cfg.in b/lib/ubsan/lit_tests/AsanConfig/lit.site.cfg.in new file mode 100644 index 0000000000000..f75741838f83d --- /dev/null +++ b/lib/ubsan/lit_tests/AsanConfig/lit.site.cfg.in @@ -0,0 +1,9 @@ +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.configured") + +# Tool-specific config options. +config.ubsan_lit_tests_dir = "@UBSAN_LIT_TESTS_DIR@" + +# Load tool-specific config that would do the real work. +print config.ubsan_lit_tests_dir +lit_config.load_config(config, "@UBSAN_LIT_TESTS_DIR@/AsanConfig/lit.cfg") diff --git a/lib/ubsan/lit_tests/CMakeLists.txt b/lib/ubsan/lit_tests/CMakeLists.txt index 7e1a13c782d2f..36d8dc1f9205c 100644 --- a/lib/ubsan/lit_tests/CMakeLists.txt +++ b/lib/ubsan/lit_tests/CMakeLists.txt @@ -1,21 +1,23 @@ +set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/UbsanConfig/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/UbsanConfig/lit.site.cfg) + configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg - ) + ${CMAKE_CURRENT_SOURCE_DIR}/AsanConfig/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/AsanConfig/lit.site.cfg) if(COMPILER_RT_CAN_EXECUTE_TESTS) # Run UBSan output tests only if we're sure that clang would produce # working binaries. set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} - ${UBSAN_RUNTIME_LIBRARIES}) - set(UBSAN_TEST_PARAMS - ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg - ) + ${UBSAN_RUNTIME_LIBRARIES} + asan_runtime_libraries) add_lit_testsuite(check-ubsan "Running UndefinedBehaviorSanitizer tests" - ${CMAKE_CURRENT_BINARY_DIR} - PARAMS ${UBSAN_TEST_PARAMS} - DEPENDS ${UBSAN_TEST_DEPS} - ) + ${CMAKE_CURRENT_BINARY_DIR}/UbsanConfig + ${CMAKE_CURRENT_BINARY_DIR}/AsanConfig + DEPENDS ${UBSAN_TEST_DEPS}) set_target_properties(check-ubsan PROPERTIES FOLDER "UBSan unittests") endif() diff --git a/lib/ubsan/lit_tests/Integer/div-zero.cpp b/lib/ubsan/lit_tests/Integer/div-zero.cpp deleted file mode 100644 index b2a839566c5f6..0000000000000 --- a/lib/ubsan/lit_tests/Integer/div-zero.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clang -fsanitize=integer-divide-by-zero -DDIVIDEND=0 %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -fsanitize=integer-divide-by-zero -DDIVIDEND=1U %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -fsanitize=float-divide-by-zero -DDIVIDEND=1.5 %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -fsanitize=integer-divide-by-zero -DDIVIDEND='intmax(123)' %s -o %t && %t 2>&1 | FileCheck %s - -#ifdef __SIZEOF_INT128__ -typedef __int128 intmax; -#else -typedef long long intmax; -#endif - -int main() { - // CHECK: div-zero.cpp:[[@LINE+1]]:12: runtime error: division by zero - DIVIDEND / 0; -} diff --git a/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp b/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp deleted file mode 100644 index 48b68b6365c66..0000000000000 --- a/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// RUN: %clang -DOP=n++ -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -DOP=++n -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -DOP=m-- -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s -// RUN: %clang -DOP=--m -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s - -#include <stdint.h> - -int main() { - int n = 0x7ffffffd; - n++; - n++; - int m = -n - 1; - // CHECK: incdec-overflow.cpp:15:3: runtime error: signed integer overflow: [[MINUS:-?]]214748364 - // CHECK: + [[MINUS]]1 cannot be represented in type 'int' - OP; -} diff --git a/lib/ubsan/lit_tests/Integer/shift.cpp b/lib/ubsan/lit_tests/Integer/shift.cpp deleted file mode 100644 index 19101c53e75ed..0000000000000 --- a/lib/ubsan/lit_tests/Integer/shift.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %clang -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=LSH_OVERFLOW -// RUN: %clang -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=LSH_OVERFLOW -// RUN: %clang -DTOO_LOW -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW -// RUN: %clang -DTOO_LOW -DOP='>>' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW -// RUN: %clang -DTOO_LOW -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW -// RUN: %clang -DTOO_LOW -DOP='>>=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW -// RUN: %clang -DTOO_HIGH -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH -// RUN: %clang -DTOO_HIGH -DOP='>>' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH -// RUN: %clang -DTOO_HIGH -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH -// RUN: %clang -DTOO_HIGH -DOP='>>=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH - -#include <stdint.h> - -int main() { - int a = 1; - unsigned b = 1; - - a <<= 31; // ok in C++11, not ok in C99/C11 - b <<= 31; // ok - b <<= 1; // still ok, unsigned - -#ifdef LSH_OVERFLOW - // CHECK-LSH_OVERFLOW: shift.cpp:24:5: runtime error: left shift of negative value -2147483648 - a OP 1; -#endif - -#ifdef TOO_LOW - // CHECK-TOO_LOW: shift.cpp:29:5: runtime error: shift exponent -3 is negative - a OP (-3); -#endif - -#ifdef TOO_HIGH - a = 0; - // CHECK-TOO_HIGH: shift.cpp:35:5: runtime error: shift exponent 32 is too large for 32-bit type 'int' - a OP 32; -#endif -} diff --git a/lib/ubsan/lit_tests/Integer/uincdec-overflow.cpp b/lib/ubsan/lit_tests/Integer/uincdec-overflow.cpp deleted file mode 100644 index 6b677ca5bd353..0000000000000 --- a/lib/ubsan/lit_tests/Integer/uincdec-overflow.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// RUN: %clang -DOP=n++ -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=INC %s -// RUN: %clang -DOP=++n -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=INC %s -// RUN: %clang -DOP=m-- -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=DEC %s -// RUN: %clang -DOP=--m -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=DEC %s - -#include <stdint.h> - -int main() { - unsigned n = 0xfffffffd; - n++; - n++; - unsigned m = 0; - // CHECK-INC: uincdec-overflow.cpp:15:3: runtime error: unsigned integer overflow: 4294967295 + 1 cannot be represented in type 'unsigned int' - // CHECK-DEC: uincdec-overflow.cpp:15:3: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int' - OP; -} diff --git a/lib/ubsan/lit_tests/Misc/bool.cpp b/lib/ubsan/lit_tests/Misc/bool.cpp deleted file mode 100644 index 8fafe7eac0531..0000000000000 --- a/lib/ubsan/lit_tests/Misc/bool.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// RUN: %clang -fsanitize=bool %s -O3 -o %T/bool.exe && %T/bool.exe 2>&1 | FileCheck %s - -unsigned char NotABool = 123; - -int main(int argc, char **argv) { - bool *p = (bool*)&NotABool; - - // FIXME: Provide a better source location here. - // CHECK: bool.exe:0x{{[0-9a-f]*}}: runtime error: load of value 123, which is not a valid value for type 'bool' - return *p; -} diff --git a/lib/ubsan/lit_tests/Float/cast-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Float/cast-overflow.cpp index 8d9120d586a16..35f9336c904a7 100644 --- a/lib/ubsan/lit_tests/Float/cast-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Float/cast-overflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=float-cast-overflow %s -o %t +// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t // RUN: %t _ // RUN: %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0 // RUN: %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1 diff --git a/lib/ubsan/lit_tests/Integer/add-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/add-overflow.cpp index 80543524f51d2..412eb7621033b 100644 --- a/lib/ubsan/lit_tests/Integer/add-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/add-overflow.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -DADD_I32 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I32 -// RUN: %clang -DADD_I64 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I64 -// RUN: %clang -DADD_I128 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I128 +// RUN: %clangxx -DADD_I32 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I32 +// RUN: %clangxx -DADD_I64 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I64 +// RUN: %clangxx -DADD_I128 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I128 #include <stdint.h> #include <stdio.h> diff --git a/lib/ubsan/lit_tests/Integer/div-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/div-overflow.cpp index dd82427f9d5b1..83aa854485b40 100644 --- a/lib/ubsan/lit_tests/Integer/div-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/div-overflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s #include <stdint.h> diff --git a/lib/ubsan/lit_tests/TestCases/Integer/div-zero.cpp b/lib/ubsan/lit_tests/TestCases/Integer/div-zero.cpp new file mode 100644 index 0000000000000..6b8aadfe15e69 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/div-zero.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND=0 %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND=1U %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=float-divide-by-zero -DDIVIDEND=1.5 %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=integer-divide-by-zero -DDIVIDEND='intmax(123)' %s -o %t && %t 2>&1 | FileCheck %s + +#ifdef __SIZEOF_INT128__ +typedef __int128 intmax; +#else +typedef long long intmax; +#endif + +int main() { + // CHECK: div-zero.cpp:[[@LINE+1]]:12: runtime error: division by zero + DIVIDEND / 0; +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/incdec-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/incdec-overflow.cpp new file mode 100644 index 0000000000000..904250a76c793 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/incdec-overflow.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx -DOP=n++ -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -DOP=++n -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -DOP=m-- -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -DOP=--m -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s + +#include <stdint.h> + +int main() { + int n = 0x7ffffffd; + n++; + n++; + int m = -n - 1; + // CHECK: incdec-overflow.cpp:15:3: runtime error: signed integer overflow: [[MINUS:-?]]214748364 + // CHECK: + [[MINUS]]1 cannot be represented in type 'int' + OP; +} diff --git a/lib/ubsan/lit_tests/Integer/mul-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/mul-overflow.cpp index 8d1e70d6ad48c..1cfe23f57213c 100644 --- a/lib/ubsan/lit_tests/Integer/mul-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/mul-overflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s #include <stdint.h> diff --git a/lib/ubsan/lit_tests/Integer/negate-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/negate-overflow.cpp index 2ee4f10115e81..6bee3eea29802 100644 --- a/lib/ubsan/lit_tests/Integer/negate-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/negate-overflow.cpp @@ -1,5 +1,5 @@ -// RUN: %clang -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECKS -// RUN: %clang -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECKU +// RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECKS +// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECKU int main() { // CHECKS-NOT: runtime error diff --git a/lib/ubsan/lit_tests/Integer/no-recover.cpp b/lib/ubsan/lit_tests/TestCases/Integer/no-recover.cpp index e200feaa79ae4..64787b7cfbf55 100644 --- a/lib/ubsan/lit_tests/Integer/no-recover.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/no-recover.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=RECOVER -// RUN: %clang -fsanitize=unsigned-integer-overflow -fsanitize-recover %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=RECOVER -// RUN: %clang -fsanitize=unsigned-integer-overflow -fno-sanitize-recover %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ABORT +// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=RECOVER +// RUN: %clangxx -fsanitize=unsigned-integer-overflow -fsanitize-recover %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=RECOVER +// RUN: %clangxx -fsanitize=unsigned-integer-overflow -fno-sanitize-recover %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ABORT #include <stdint.h> @@ -17,6 +17,6 @@ int main() { // ABORT: no-recover.cpp:[[@LINE-2]]:5: runtime error: unsigned integer overflow: 2271560481 + 3989547399 cannot be represented in type 'unsigned int' (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); - // RECOVER: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned long' + // RECOVER: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' // ABORT-NOT: runtime error } diff --git a/lib/ubsan/lit_tests/TestCases/Integer/shift.cpp b/lib/ubsan/lit_tests/TestCases/Integer/shift.cpp new file mode 100644 index 0000000000000..f35fa1f959ae5 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/shift.cpp @@ -0,0 +1,37 @@ +// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW +// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW +// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW +// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW +// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW +// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW +// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH +// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH +// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH +// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH + +#include <stdint.h> + +int main() { + int a = 1; + unsigned b = 1; + + a <<= 31; // ok in C++11, not ok in C99/C11 + b <<= 31; // ok + b <<= 1; // still ok, unsigned + +#ifdef LSH_OVERFLOW + // CHECK-LSH_OVERFLOW: shift.cpp:24:5: runtime error: left shift of negative value -2147483648 + a OP 1; +#endif + +#ifdef TOO_LOW + // CHECK-TOO_LOW: shift.cpp:29:5: runtime error: shift exponent -3 is negative + a OP (-3); +#endif + +#ifdef TOO_HIGH + a = 0; + // CHECK-TOO_HIGH: shift.cpp:35:5: runtime error: shift exponent 32 is too large for 32-bit type 'int' + a OP 32; +#endif +} diff --git a/lib/ubsan/lit_tests/Integer/sub-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/sub-overflow.cpp index b43a69bee4e6d..bf33d293799bb 100644 --- a/lib/ubsan/lit_tests/Integer/sub-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/sub-overflow.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -DSUB_I32 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I32 -// RUN: %clang -DSUB_I64 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I64 -// RUN: %clang -DSUB_I128 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I128 +// RUN: %clangxx -DSUB_I32 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I32 +// RUN: %clangxx -DSUB_I64 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I64 +// RUN: %clangxx -DSUB_I128 -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I128 #include <stdint.h> #include <stdio.h> diff --git a/lib/ubsan/lit_tests/Integer/uadd-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/uadd-overflow.cpp index 0edb10092e2c5..2ef31c0640d15 100644 --- a/lib/ubsan/lit_tests/Integer/uadd-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/uadd-overflow.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -DADD_I32 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I32 -// RUN: %clang -DADD_I64 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I64 -// RUN: %clang -DADD_I128 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I128 +// RUN: %clangxx -DADD_I32 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I32 +// RUN: %clangxx -DADD_I64 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I64 +// RUN: %clangxx -DADD_I128 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-ADD_I128 #include <stdint.h> #include <stdio.h> @@ -18,7 +18,7 @@ int main() { #ifdef ADD_I64 (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); - // CHECK-ADD_I64: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned long' + // CHECK-ADD_I64: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' #endif #ifdef ADD_I128 diff --git a/lib/ubsan/lit_tests/TestCases/Integer/uincdec-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/uincdec-overflow.cpp new file mode 100644 index 0000000000000..a14bd6a776f51 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/uincdec-overflow.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx -DOP=n++ -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=CHECK-INC %s +// RUN: %clangxx -DOP=++n -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=CHECK-INC %s +// RUN: %clangxx -DOP=m-- -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=CHECK-DEC %s +// RUN: %clangxx -DOP=--m -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck --check-prefix=CHECK-DEC %s + +#include <stdint.h> + +int main() { + unsigned n = 0xfffffffd; + n++; + n++; + unsigned m = 0; + // CHECK-INC: uincdec-overflow.cpp:15:3: runtime error: unsigned integer overflow: 4294967295 + 1 cannot be represented in type 'unsigned int' + // CHECK-DEC: uincdec-overflow.cpp:15:3: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int' + OP; +} diff --git a/lib/ubsan/lit_tests/Integer/umul-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/umul-overflow.cpp index 42cf3a780ed0e..c84bb39ef2f73 100644 --- a/lib/ubsan/lit_tests/Integer/umul-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/umul-overflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s #include <stdint.h> diff --git a/lib/ubsan/lit_tests/Integer/usub-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/usub-overflow.cpp index 357d662ad63e2..78f7455785833 100644 --- a/lib/ubsan/lit_tests/Integer/usub-overflow.cpp +++ b/lib/ubsan/lit_tests/TestCases/Integer/usub-overflow.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -DSUB_I32 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I32 -// RUN: %clang -DSUB_I64 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I64 -// RUN: %clang -DSUB_I128 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I128 +// RUN: %clangxx -DSUB_I32 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I32 +// RUN: %clangxx -DSUB_I64 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I64 +// RUN: %clangxx -DSUB_I128 -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUB_I128 #include <stdint.h> #include <stdio.h> @@ -17,7 +17,7 @@ int main() { #ifdef SUB_I64 (void)(uint64_t(8000000000000000000ll) - uint64_t(9000000000000000000ll)); - // CHECK-SUB_I64: 8000000000000000000 - 9000000000000000000 cannot be represented in type 'unsigned long' + // CHECK-SUB_I64: 8000000000000000000 - 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' #endif #ifdef SUB_I128 diff --git a/lib/ubsan/lit_tests/TestCases/Misc/bool.cpp b/lib/ubsan/lit_tests/TestCases/Misc/bool.cpp new file mode 100644 index 0000000000000..e916e7fb3c1d5 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/bool.cpp @@ -0,0 +1,10 @@ +// RUN: %clangxx -fsanitize=bool %s -O3 -o %T/bool.exe && %T/bool.exe 2>&1 | FileCheck %s + +unsigned char NotABool = 123; + +int main(int argc, char **argv) { + bool *p = (bool*)&NotABool; + + // CHECK: bool.cpp:9:10: runtime error: load of value 123, which is not a valid value for type 'bool' + return *p; +} diff --git a/lib/ubsan/lit_tests/Misc/bounds.cpp b/lib/ubsan/lit_tests/TestCases/Misc/bounds.cpp index 07b30d384df96..dc4c4a513c1cc 100644 --- a/lib/ubsan/lit_tests/Misc/bounds.cpp +++ b/lib/ubsan/lit_tests/TestCases/Misc/bounds.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=bounds %s -O3 -o %T/bounds.exe +// RUN: %clangxx -fsanitize=bounds %s -O3 -o %T/bounds.exe // RUN: %T/bounds.exe 0 0 0 // RUN: %T/bounds.exe 1 2 3 // RUN: %T/bounds.exe 2 0 0 2>&1 | FileCheck %s --check-prefix=CHECK-A-2 diff --git a/lib/ubsan/lit_tests/Misc/deduplication.cpp b/lib/ubsan/lit_tests/TestCases/Misc/deduplication.cpp index d9c909f9af4f8..d325bf6dd8997 100644 --- a/lib/ubsan/lit_tests/Misc/deduplication.cpp +++ b/lib/ubsan/lit_tests/TestCases/Misc/deduplication.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=undefined %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=undefined %s -o %t && %t 2>&1 | FileCheck %s // Verify deduplication works by ensuring only one diag is emitted. #include <limits.h> #include <stdio.h> diff --git a/lib/ubsan/lit_tests/Misc/enum.cpp b/lib/ubsan/lit_tests/TestCases/Misc/enum.cpp index b363fea3487f1..c5642507ad424 100644 --- a/lib/ubsan/lit_tests/Misc/enum.cpp +++ b/lib/ubsan/lit_tests/TestCases/Misc/enum.cpp @@ -1,6 +1,6 @@ -// RUN: %clang -fsanitize=enum %s -O3 -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-PLAIN -// RUN: %clang -fsanitize=enum -std=c++11 -DE="class E" %s -O3 -o %t && %t -// RUN: %clang -fsanitize=enum -std=c++11 -DE="class E : bool" %s -O3 -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-BOOL +// RUN: %clangxx -fsanitize=enum %s -O3 -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-PLAIN +// RUN: %clangxx -fsanitize=enum -std=c++11 -DE="class E" %s -O3 -o %t && %t +// RUN: %clangxx -fsanitize=enum -std=c++11 -DE="class E : bool" %s -O3 -o %t && %t 2>&1 | FileCheck %s --check-prefix=CHECK-BOOL enum E { a = 1 } e; #undef E diff --git a/lib/ubsan/lit_tests/Misc/missing_return.cpp b/lib/ubsan/lit_tests/TestCases/Misc/missing_return.cpp index 9997b8386f21b..7da238e25dca6 100644 --- a/lib/ubsan/lit_tests/Misc/missing_return.cpp +++ b/lib/ubsan/lit_tests/TestCases/Misc/missing_return.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=return %s -O3 -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=return %s -O3 -o %t && %t 2>&1 | FileCheck %s // CHECK: missing_return.cpp:4:5: runtime error: execution reached the end of a value-returning function without returning a value int f() { diff --git a/lib/ubsan/lit_tests/Misc/unreachable.cpp b/lib/ubsan/lit_tests/TestCases/Misc/unreachable.cpp index 5ca4e5fd8b0c0..75fc3e5bd9a69 100644 --- a/lib/ubsan/lit_tests/Misc/unreachable.cpp +++ b/lib/ubsan/lit_tests/TestCases/Misc/unreachable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=unreachable %s -O3 -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=unreachable %s -O3 -o %t && %t 2>&1 | FileCheck %s int main(int, char **argv) { // CHECK: unreachable.cpp:5:3: runtime error: execution reached a __builtin_unreachable() call diff --git a/lib/ubsan/lit_tests/Misc/vla.c b/lib/ubsan/lit_tests/TestCases/Misc/vla.c index 2fa88addc0d36..2fa88addc0d36 100644 --- a/lib/ubsan/lit_tests/Misc/vla.c +++ b/lib/ubsan/lit_tests/TestCases/Misc/vla.c diff --git a/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/function.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/function.cpp new file mode 100644 index 0000000000000..8106ae47ee4fa --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/function.cpp @@ -0,0 +1,17 @@ +// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t +// RUN: %t 2>&1 | FileCheck %s + +#include <stdint.h> + +void f() {} + +void g(int x) {} + +int main(void) { + // CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)' + // CHECK-NEXT: function.cpp:6: note: f() defined here + reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42); + + // CHECK-NOT: runtime error: call to function g + reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42); +} diff --git a/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/lit.local.cfg b/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/lit.local.cfg new file mode 100644 index 0000000000000..27c61a34387cd --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/Function/lit.local.cfg @@ -0,0 +1,3 @@ +# The function type checker is only supported on x86 and x86_64 for now. +if config.root.host_arch not in ['x86', 'x86_64']: + config.unsupported = True diff --git a/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/misaligned.cpp index 3abacae8be896..9b0b9a1197c0b 100644 --- a/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/misaligned.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=alignment %s -O3 -o %t +// RUN: %clangxx -fsanitize=alignment %s -O3 -o %t // RUN: %t l0 && %t s0 && %t r0 && %t m0 && %t f0 && %t n0 // RUN: %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --strict-whitespace // RUN: %t s1 2>&1 | FileCheck %s --check-prefix=CHECK-STORE @@ -64,7 +64,7 @@ int main(int, char **argv) { case 'n': // FIXME: Provide a better source location here. - // CHECK-NEW: misaligned{{.*}}:0x{{[0-9a-f]*}}: runtime error: constructor call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment + // CHECK-NEW: misaligned{{.*}}+0x{{[0-9a-f]*}}): runtime error: constructor call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment // CHECK-NEW-NEXT: [[PTR]]: note: pointer points here // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04 05}} // CHECK-NEW-NEXT: {{^ \^}} diff --git a/lib/ubsan/lit_tests/TypeCheck/null.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/null.cpp index f72af28ce1605..79726924d2131 100644 --- a/lib/ubsan/lit_tests/TypeCheck/null.cpp +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/null.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -fsanitize=null %s -O3 -o %t +// RUN: %clangxx -fsanitize=null %s -O3 -o %t // RUN: %t l 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD // RUN: %t s 2>&1 | FileCheck %s --check-prefix=CHECK-STORE // RUN: %t r 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE diff --git a/lib/ubsan/lit_tests/TypeCheck/vptr.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/vptr.cpp index 109e7a824f58b..9095f7279a663 100644 --- a/lib/ubsan/lit_tests/TypeCheck/vptr.cpp +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/vptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -ccc-cxx -fsanitize=vptr %s -O3 -o %t +// RUN: %clangxx -fsanitize=vptr %s -O3 -o %t // RUN: %t rT && %t mT && %t fT && %t cT // RUN: %t rU && %t mU && %t fU && %t cU // RUN: %t rS && %t rV && %t oV @@ -101,7 +101,7 @@ int main(int, char **argv) { // CHECK-OFFSET: vptr.cpp:[[@LINE+5]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'U' // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class subobject at offset {{8|16}} within object of type [[DYN_TYPE:'U']] // CHECK-OFFSET-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. }} - // CHECK-OFFSET-NEXT: {{^ \^ ( ~~~~~~~~~~~~)~~~~~~~~~~~ *$}} + // CHECK-OFFSET-NEXT: {{^ \^ ( ~~~~~~~~~~~~)?~~~~~~~~~~~ *$}} // CHECK-OFFSET-NEXT: {{^ ( )?vptr for}} 'T' base class of [[DYN_TYPE]] return reinterpret_cast<U*>(p)->v() - 2; diff --git a/lib/ubsan/lit_tests/UbsanConfig/lit.cfg b/lib/ubsan/lit_tests/UbsanConfig/lit.cfg new file mode 100644 index 0000000000000..fcc93035c6005 --- /dev/null +++ b/lib/ubsan/lit_tests/UbsanConfig/lit.cfg @@ -0,0 +1,23 @@ +# -*- Python -*- + +import os + +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if not attr_value: + lit_config.fatal( + "No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg " % attr_name) + return attr_value + +ubsan_lit_tests_dir = get_required_attr(config, "ubsan_lit_tests_dir") +ubsan_lit_cfg = os.path.join(ubsan_lit_tests_dir, "lit.common.cfg") +lit_config.load_config(config, ubsan_lit_cfg) + +config.name = 'UndefinedBehaviorSanitizer-Standalone' + +# Define %clang and %clangxx substitutions to use in test RUN lines. +config.substitutions.append( ("%clang ", (" " + config.clang + " ")) ) +config.substitutions.append( ("%clangxx ", (" " + config.clang + + " --driver-mode=g++ ")) ) diff --git a/lib/ubsan/lit_tests/UbsanConfig/lit.site.cfg.in b/lib/ubsan/lit_tests/UbsanConfig/lit.site.cfg.in new file mode 100644 index 0000000000000..c08fc30d00429 --- /dev/null +++ b/lib/ubsan/lit_tests/UbsanConfig/lit.site.cfg.in @@ -0,0 +1,8 @@ +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.configured") + +# Tool-specific config options. +config.ubsan_lit_tests_dir = "@UBSAN_LIT_TESTS_DIR@" + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@UBSAN_LIT_TESTS_DIR@/UbsanConfig/lit.cfg") diff --git a/lib/ubsan/lit_tests/lit.cfg b/lib/ubsan/lit_tests/lit.cfg deleted file mode 100644 index ea6ebdf9001f8..0000000000000 --- a/lib/ubsan/lit_tests/lit.cfg +++ /dev/null @@ -1,66 +0,0 @@ -# -*- Python -*- - -import os - -def get_required_attr(config, attr_name): - attr_value = getattr(config, attr_name, None) - if not attr_value: - lit.fatal("No attribute %r in test configuration! You may need to run " - "tests from your build directory or add this attribute " - "to lit.site.cfg " % attr_name) - return attr_value - -# Setup config name. -config.name = 'UndefinedBehaviorSanitizer' - -# Setup source root. -config.test_source_root = os.path.dirname(__file__) - -def DisplayNoConfigMessage(): - lit.fatal("No site specific configuration available! " + - "Try running your test from the build tree or running " + - "make check-ubsan") - -# Figure out LLVM source root. -llvm_src_root = getattr(config, 'llvm_src_root', None) -if llvm_src_root is None: - # We probably haven't loaded the site-specific configuration: the user - # is likely trying to run a test file directly, and the site configuration - # wasn't created by the build system or we're performing an out-of-tree build. - ubsan_site_cfg = lit.params.get('ubsan_site_config', None) - if ubsan_site_cfg and os.path.exists(ubsan_site_cfg): - lit.load_config(config, ubsan_site_cfg) - raise SystemExit - - # Try to guess the location of site-specific configuration using llvm-config - # util that can point where the build tree is. - llvm_config = lit.util.which("llvm-config", config.environment["PATH"]) - if not llvm_config: - DisplayNoConfigMessage() - - # Find out the presumed location of generated site config. - llvm_obj_root = lit.util.capture(["llvm-config", "--obj-root"]).strip() - ubsan_site_cfg = os.path.join(llvm_obj_root, "projects", "compiler-rt", - "lib", "ubsan", "lit_tests", "lit.site.cfg") - if not ubsan_site_cfg or not os.path.exists(ubsan_site_cfg): - DisplayNoConfigMessage() - - lit.load_config(config, ubsan_site_cfg) - raise SystemExit - -# Setup attributes common for all compiler-rt projects. -compiler_rt_src_root = get_required_attr(config, 'compiler_rt_src_root') -compiler_rt_lit_cfg = os.path.join(compiler_rt_src_root, "lib", - "lit.common.cfg") -if not compiler_rt_lit_cfg or not os.path.exists(compiler_rt_lit_cfg): - lit.fatal("Can't find common compiler-rt lit config at: %r" - % compiler_rt_lit_cfg) -lit.load_config(config, compiler_rt_lit_cfg) - -# Default test suffixes. -config.suffixes = ['.c', '.cc', '.cpp'] - -# UndefinedBehaviorSanitizer tests are currently supported on -# Linux and Darwin only. -if config.host_os not in ['Linux', 'Darwin']: - config.unsupported = True diff --git a/lib/ubsan/lit_tests/lit.common.cfg b/lib/ubsan/lit_tests/lit.common.cfg new file mode 100644 index 0000000000000..23c85e9fa0659 --- /dev/null +++ b/lib/ubsan/lit_tests/lit.common.cfg @@ -0,0 +1,31 @@ +# -*- Python -*- + +import os + +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if not attr_value: + lit_config.fatal( + "No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg " % attr_name) + return attr_value + +# Setup source root. +ubsan_lit_tests_dir = get_required_attr(config, 'ubsan_lit_tests_dir') +config.test_source_root = os.path.join(ubsan_lit_tests_dir, 'TestCases') + +def DisplayNoConfigMessage(): + lit_config.fatal("No site specific configuration available! " + + "Try running your test from the build tree or running " + + "make check-ubsan") + +# Default test suffixes. +config.suffixes = ['.c', '.cc', '.cpp'] + +# UndefinedBehaviorSanitizer tests are currently supported on +# Linux and Darwin only. +if config.host_os not in ['Linux', 'Darwin']: + config.unsupported = True + +config.pipefail = False diff --git a/lib/ubsan/lit_tests/lit.site.cfg.in b/lib/ubsan/lit_tests/lit.site.cfg.in deleted file mode 100644 index 07b521af061f7..0000000000000 --- a/lib/ubsan/lit_tests/lit.site.cfg.in +++ /dev/null @@ -1,20 +0,0 @@ -## Autogenerated by LLVM/Clang configuration. -# Do not edit! - -config.clang = "@LLVM_BINARY_DIR@/bin/clang" -config.host_os = "@HOST_OS@" -config.llvm_src_root = "@LLVM_SOURCE_DIR@" -config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@" -config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" -config.target_triple = "@TARGET_TRIPLE@" - -# LLVM tools dir can be passed in lit parameters, so try to -# apply substitution. -try: - config.llvm_tools_dir = config.llvm_tools_dir % lit.params -except KeyError,e: - key, = e.args - lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key, key)) - -# Let the main config do the real work. -lit.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/lib/ubsan/ubsan.syms b/lib/ubsan/ubsan.syms deleted file mode 100644 index e74de33f012ce..0000000000000 --- a/lib/ubsan/ubsan.syms +++ /dev/null @@ -1 +0,0 @@ -{ __ubsan_*; }; diff --git a/lib/ubsan/ubsan.syms.extra b/lib/ubsan/ubsan.syms.extra new file mode 100644 index 0000000000000..7f8be694401af --- /dev/null +++ b/lib/ubsan/ubsan.syms.extra @@ -0,0 +1 @@ +__ubsan_* diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc index 3f92761465dee..fa643658ea363 100644 --- a/lib/ubsan/ubsan_diag.cc +++ b/lib/ubsan/ubsan_diag.cc @@ -26,11 +26,21 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) { return Location(); uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc); + return getFunctionLocation(Loc, 0); +} + +Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) { + if (!Loc) + return Location(); AddressInfo Info; - if (!SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module) + if (!Symbolizer::GetOrInit()->SymbolizeCode(Loc, &Info, 1) || + !Info.module || !*Info.module) return Location(Loc); + if (FName && Info.function) + *FName = Info.function; + if (!Info.file) return ModuleLocation(Info.module, Info.module_offset); @@ -67,29 +77,29 @@ static void PrintHex(UIntMax Val) { } static void renderLocation(Location Loc) { + InternalScopedString LocBuffer(1024); switch (Loc.getKind()) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); if (SLoc.isInvalid()) - Printf("<unknown>:"); - else { - Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine()); - if (SLoc.getColumn()) - Printf("%d:", SLoc.getColumn()); - } + LocBuffer.append("<unknown>"); + else + PrintSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(), + SLoc.getColumn()); break; } case Location::LK_Module: - Printf("%s:0x%zx:", Loc.getModuleLocation().getModuleName(), - Loc.getModuleLocation().getOffset()); + PrintModuleAndOffset(&LocBuffer, Loc.getModuleLocation().getModuleName(), + Loc.getModuleLocation().getOffset()); break; case Location::LK_Memory: - Printf("%p:", Loc.getMemoryLocation()); + LocBuffer.append("%p", Loc.getMemoryLocation()); break; case Location::LK_Null: - Printf("<unknown>:"); + LocBuffer.append("<unknown>"); break; } + Printf("%s:", LocBuffer.data()); } static void renderText(const char *Message, const Diag::Arg *Args) { @@ -109,7 +119,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) { Printf("%s", A.String); break; case Diag::AK_Mangled: { - Printf("'%s'", Demangle(A.String)); + Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A.String)); break; } case Diag::AK_SInt: diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index 16afffdb0a76d..54d15a0cc1bad 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -80,6 +80,12 @@ public: /// an invalid location or a module location for the caller. Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC()); +/// Try to obtain a location for the given function pointer. This might fail, +/// and produce either an invalid location or a module location for the caller. +/// If FName is non-null and the name of the function is known, set *FName to +/// the function name, otherwise *FName is unchanged. +Location getFunctionLocation(uptr Loc, const char **FName); + /// A diagnostic severity level. enum DiagLevel { DL_Error, ///< An error. diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index fa93b095d0bb4..d55643143295c 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -246,15 +246,36 @@ void __ubsan::__ubsan_handle_float_cast_overflow_abort( void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data, ValueHandle Val) { - // TODO: Add deduplication once a SourceLocation is generated for this check. - Diag(getCallerLocation(), DL_Error, + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") << Value(Data->Type, Val) << Data->Type; } void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, ValueHandle Val) { - Diag(getCallerLocation(), DL_Error, - "load of value %0, which is not a valid value for type %1") - << Value(Data->Type, Val) << Data->Type; + __ubsan_handle_load_invalid_value(Data, Val); + Die(); +} + +void __ubsan::__ubsan_handle_function_type_mismatch( + FunctionTypeMismatchData *Data, + ValueHandle Function) { + const char *FName = "(unknown)"; + + Location Loc = getFunctionLocation(Function, &FName); + + Diag(Data->Loc, DL_Error, + "call to function %0 through pointer to incorrect function type %1") + << FName << Data->Type; + Diag(Loc, DL_Note, "%0 defined here") << FName; +} + +void __ubsan::__ubsan_handle_function_type_mismatch_abort( + FunctionTypeMismatchData *Data, + ValueHandle Function) { + __ubsan_handle_function_type_mismatch(Data, Function); Die(); } diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 5e237e1aa2de2..14e6f04c2a1b8 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -105,13 +105,22 @@ struct FloatCastOverflowData { RECOVERABLE(float_cast_overflow, FloatCastOverflowData *Data, ValueHandle From) struct InvalidValueData { - // FIXME: SourceLocation Loc; + SourceLocation Loc; const TypeDescriptor &Type; }; /// \brief Handle a load of an invalid value for the type. RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val) +struct FunctionTypeMismatchData { + SourceLocation Loc; + const TypeDescriptor &Type; +}; + +RECOVERABLE(function_type_mismatch, + FunctionTypeMismatchData *Data, + ValueHandle Val) + } #endif // UBSAN_HANDLERS_H diff --git a/lib/ubsan/ubsan_type_hash.cc b/lib/ubsan/ubsan_type_hash.cc index b27aefc16821d..a388bcc6d72e8 100644 --- a/lib/ubsan/ubsan_type_hash.cc +++ b/lib/ubsan/ubsan_type_hash.cc @@ -85,16 +85,18 @@ namespace abi = __cxxabiv1; // reused as needed. The second caching layer is a large hash table with open // chaining. We can freely evict from either layer since this is just a cache. // -// FIXME: Make these hash table accesses thread-safe. The races here are benign -// (worst-case, we could miss a bug or see a slowdown) but we should -// avoid upsetting race detectors. +// FIXME: Make these hash table accesses thread-safe. The races here are benign: +// assuming the unsequenced loads and stores don't misbehave too badly, +// the worst case is false negatives or poor cache behavior, not false +// positives or crashes. /// Find a bucket to store the given hash value in. static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) { static const unsigned HashTableSize = 65537; - static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize] = { 1 }; + static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize]; - unsigned Probe = V & 65535; + unsigned First = (V & 65535) ^ 1; + unsigned Probe = First; for (int Tries = 5; Tries; --Tries) { if (!__ubsan_vptr_hash_set[Probe] || __ubsan_vptr_hash_set[Probe] == V) return &__ubsan_vptr_hash_set[Probe]; @@ -104,12 +106,12 @@ static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) { } // FIXME: Pick a random entry from the probe sequence to evict rather than // just taking the first. - return &__ubsan_vptr_hash_set[V]; + return &__ubsan_vptr_hash_set[First]; } /// A cache of recently-checked hashes. Mini hash table with "random" evictions. __ubsan::HashValue -__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize] = { 1 }; +__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize]; /// \brief Determine whether \p Derived has a \p Base base class subobject at /// offset \p Offset. |