diff options
Diffstat (limited to 'lib/ubsan/lit_tests/TestCases')
26 files changed, 727 insertions, 0 deletions
diff --git a/lib/ubsan/lit_tests/TestCases/Float/cast-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Float/cast-overflow.cpp new file mode 100644 index 000000000000..35f9336c904a --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Float/cast-overflow.cpp @@ -0,0 +1,99 @@ +// 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 +// RUN: %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2 +// RUN: %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3 +// RUN: %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4 +// RUN: %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5 +// RUN: %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6 +// FIXME: %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7 +// RUN: %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8 + +// This test assumes float and double are IEEE-754 single- and double-precision. + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +float Inf; +float NaN; + +int main(int argc, char **argv) { +  float MaxFloatRepresentableAsInt = 0x7fffff80; +  (int)MaxFloatRepresentableAsInt; // ok +  (int)-MaxFloatRepresentableAsInt; // ok + +  float MinFloatRepresentableAsInt = -0x7fffffff - 1; +  (int)MinFloatRepresentableAsInt; // ok + +  float MaxFloatRepresentableAsUInt = 0xffffff00u; +  (unsigned int)MaxFloatRepresentableAsUInt; // ok + +#ifdef __SIZEOF_INT128__ +  unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104); +  (void)(float)FloatMaxAsUInt128; // ok +#endif + +  float NearlyMinusOne = -0.99999; +  unsigned Zero = NearlyMinusOne; // ok + +  // Build a '+Inf'. +  char InfVal[] = { 0x00, 0x00, 0x80, 0x7f }; +  float Inf; +  memcpy(&Inf, InfVal, 4); + +  // Build a 'NaN'. +  char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f }; +  float NaN; +  memcpy(&NaN, NaNVal, 4); + +  double DblInf = (double)Inf; // ok + +  switch (argv[1][0]) { +    // FIXME: Produce a source location for these checks and test for it here. + +    // Floating point -> integer overflow. +  case '0': +    // Note that values between 0x7ffffe00 and 0x80000000 may or may not +    // successfully round-trip, depending on the rounding mode. +    // CHECK-0: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int' +    return MaxFloatRepresentableAsInt + 0x80; +  case '1': +    // CHECK-1: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int' +    return MinFloatRepresentableAsInt - 0x100; +  case '2': +    // CHECK-2: runtime error: value -1 is outside the range of representable values of type 'unsigned int' +    return (unsigned)-1.0; +  case '3': +    // CHECK-3: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int' +    return (unsigned)(MaxFloatRepresentableAsUInt + 0x100); + +  case '4': +    // CHECK-4: runtime error: value {{.*}} is outside the range of representable values of type 'int' +    return Inf; +  case '5': +    // CHECK-5: runtime error: value {{.*}} is outside the range of representable values of type 'int' +    return NaN; + +    // Integer -> floating point overflow. +  case '6': +    // CHECK-6: {{runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'|__int128 not supported}} +#ifdef __SIZEOF_INT128__ +    return (float)(FloatMaxAsUInt128 + 1); +#else +    puts("__int128 not supported"); +    return 0; +#endif +  // FIXME: The backend cannot lower __fp16 operations on x86 yet. +  //case '7': +  //  (__fp16)65504; // ok +  //  // CHECK-7: runtime error: value 65505 is outside the range of representable values of type '__fp16' +  //  return (__fp16)65505; + +    // Floating point -> floating point overflow. +  case '8': +    // CHECK-8: runtime error: value 1e+39 is outside the range of representable values of type 'float' +    return (float)1e39; +  } +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/add-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/add-overflow.cpp new file mode 100644 index 000000000000..412eb7621033 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/add-overflow.cpp @@ -0,0 +1,32 @@ +// 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> + +int main() { +  // These promote to 'int'. +  (void)(int8_t(0x7f) + int8_t(0x7f)); +  (void)(int16_t(0x3fff) + int16_t(0x4000)); + +#ifdef ADD_I32 +  int32_t k = 0x12345678; +  k += 0x789abcde; +  // CHECK-ADD_I32: add-overflow.cpp:[[@LINE-1]]:5: runtime error: signed integer overflow: 305419896 + 2023406814 cannot be represented in type 'int' +#endif + +#ifdef ADD_I64 +  (void)(int64_t(8000000000000000000ll) + int64_t(2000000000000000000ll)); +  // CHECK-ADD_I64: 8000000000000000000 + 2000000000000000000 cannot be represented in type '{{long( long)?}}' +#endif + +#ifdef ADD_I128 +# ifdef __SIZEOF_INT128__ +  (void)((__int128_t(1) << 126) + (__int128_t(1) << 126)); +# else +  puts("__int128 not supported"); +# endif +  // CHECK-ADD_I128: {{0x40000000000000000000000000000000 \+ 0x40000000000000000000000000000000 cannot be represented in type '__int128'|__int128 not supported}} +#endif +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/div-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/div-overflow.cpp new file mode 100644 index 000000000000..83aa854485b4 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/div-overflow.cpp @@ -0,0 +1,10 @@ +// RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s + +#include <stdint.h> + +int main() { +  unsigned(0x80000000) / -1; + +  // CHECK: div-overflow.cpp:9:23: runtime error: division of -2147483648 by -1 cannot be represented in type 'int' +  int32_t(0x80000000) / -1; +} 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 000000000000..6b8aadfe15e6 --- /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 000000000000..904250a76c79 --- /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/TestCases/Integer/mul-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/mul-overflow.cpp new file mode 100644 index 000000000000..1cfe23f57213 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/mul-overflow.cpp @@ -0,0 +1,14 @@ +// RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s + +#include <stdint.h> + +int main() { +  // These promote to 'int'. +  (void)(int8_t(-2) * int8_t(0x7f)); +  (void)(int16_t(0x7fff) * int16_t(0x7fff)); +  (void)(uint16_t(0xffff) * int16_t(0x7fff)); +  (void)(uint16_t(0xffff) * uint16_t(0x8000)); + +  // CHECK: mul-overflow.cpp:13:27: runtime error: signed integer overflow: 65535 * 32769 cannot be represented in type 'int' +  (void)(uint16_t(0xffff) * uint16_t(0x8001)); +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/negate-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/negate-overflow.cpp new file mode 100644 index 000000000000..6bee3eea2980 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/negate-overflow.cpp @@ -0,0 +1,12 @@ +// 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 +  // CHECKU: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of 2147483648 cannot be represented in type 'unsigned int' +  // CHECKU-NOT: cast to an unsigned +  -unsigned(-0x7fffffff - 1); // ok +  // CHECKS: negate-overflow.cpp:[[@LINE+2]]:10: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself +  // CHECKU-NOT: runtime error +  return -(-0x7fffffff - 1); +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/no-recover.cpp b/lib/ubsan/lit_tests/TestCases/Integer/no-recover.cpp new file mode 100644 index 000000000000..64787b7cfbf5 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/no-recover.cpp @@ -0,0 +1,22 @@ +// 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> + +int main() { +  // These promote to 'int'. +  (void)(uint8_t(0xff) + uint8_t(0xff)); +  (void)(uint16_t(0xf0fff) + uint16_t(0x0fff)); +  // RECOVER-NOT: runtime error +  // ABORT-NOT: runtime error + +  uint32_t k = 0x87654321; +  k += 0xedcba987; +  // RECOVER: no-recover.cpp:[[@LINE-1]]:5: runtime error: unsigned integer overflow: 2271560481 + 3989547399 cannot be represented in type 'unsigned int' +  // 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( 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 000000000000..f35fa1f959ae --- /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/TestCases/Integer/sub-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/sub-overflow.cpp new file mode 100644 index 000000000000..bf33d293799b --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/sub-overflow.cpp @@ -0,0 +1,31 @@ +// 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> + +int main() { +  // These promote to 'int'. +  (void)(int8_t(-2) - int8_t(0x7f)); +  (void)(int16_t(-2) - int16_t(0x7fff)); + +#ifdef SUB_I32 +  (void)(int32_t(-2) - int32_t(0x7fffffff)); +  // CHECK-SUB_I32: sub-overflow.cpp:[[@LINE-1]]:22: runtime error: signed integer overflow: -2 - 2147483647 cannot be represented in type 'int' +#endif + +#ifdef SUB_I64 +  (void)(int64_t(-8000000000000000000ll) - int64_t(2000000000000000000ll)); +  // CHECK-SUB_I64: -8000000000000000000 - 2000000000000000000 cannot be represented in type '{{long( long)?}}' +#endif + +#ifdef SUB_I128 +# ifdef __SIZEOF_INT128__ +  (void)(-(__int128_t(1) << 126) - (__int128_t(1) << 126) - 1); +# else +  puts("__int128 not supported"); +# endif +  // CHECK-SUB_I128: {{0x80000000000000000000000000000000 - 1 cannot be represented in type '__int128'|__int128 not supported}} +#endif +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/uadd-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/uadd-overflow.cpp new file mode 100644 index 000000000000..2ef31c0640d1 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/uadd-overflow.cpp @@ -0,0 +1,32 @@ +// 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> + +int main() { +  // These promote to 'int'. +  (void)(uint8_t(0xff) + uint8_t(0xff)); +  (void)(uint16_t(0xf0fff) + uint16_t(0x0fff)); + +#ifdef ADD_I32 +  uint32_t k = 0x87654321; +  k += 0xedcba987; +  // CHECK-ADD_I32: uadd-overflow.cpp:[[@LINE-1]]:5: runtime error: unsigned integer overflow: 2271560481 + 3989547399 cannot be represented in type 'unsigned int' +#endif + +#ifdef ADD_I64 +  (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); +  // CHECK-ADD_I64: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' +#endif + +#ifdef ADD_I128 +# ifdef __SIZEOF_INT128__ +  (void)((__uint128_t(1) << 127) + (__uint128_t(1) << 127)); +# else +  puts("__int128 not supported"); +# endif +  // CHECK-ADD_I128: {{0x80000000000000000000000000000000 \+ 0x80000000000000000000000000000000 cannot be represented in type 'unsigned __int128'|__int128 not supported}} +#endif +} 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 000000000000..a14bd6a776f5 --- /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/TestCases/Integer/umul-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/umul-overflow.cpp new file mode 100644 index 000000000000..c84bb39ef2f7 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/umul-overflow.cpp @@ -0,0 +1,19 @@ +// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %t 2>&1 | FileCheck %s + +#include <stdint.h> + +int main() { +  // These promote to 'int'. +  (void)(int8_t(-2) * int8_t(0x7f)); +  (void)(int16_t(0x7fff) * int16_t(0x7fff)); +  (void)(uint16_t(0xffff) * int16_t(0x7fff)); +  (void)(uint16_t(0xffff) * uint16_t(0x8000)); + +  // Not an unsigned overflow +  (void)(uint16_t(0xffff) * uint16_t(0x8001)); + +  (void)(uint32_t(0xffffffff) * uint32_t(0x2)); +  // CHECK: umul-overflow.cpp:15:31: runtime error: unsigned integer overflow: 4294967295 * 2 cannot be represented in type 'unsigned int' + +  return 0; +} diff --git a/lib/ubsan/lit_tests/TestCases/Integer/usub-overflow.cpp b/lib/ubsan/lit_tests/TestCases/Integer/usub-overflow.cpp new file mode 100644 index 000000000000..78f745578583 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Integer/usub-overflow.cpp @@ -0,0 +1,31 @@ +// 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> + +int main() { +  // These promote to 'int'. +  (void)(uint8_t(0) - uint8_t(0x7f)); +  (void)(uint16_t(0) - uint16_t(0x7fff)); + +#ifdef SUB_I32 +  (void)(uint32_t(1) - uint32_t(2)); +  // CHECK-SUB_I32: usub-overflow.cpp:[[@LINE-1]]:22: runtime error: unsigned integer overflow: 1 - 2 cannot be represented in type 'unsigned int' +#endif + +#ifdef SUB_I64 +  (void)(uint64_t(8000000000000000000ll) - uint64_t(9000000000000000000ll)); +  // CHECK-SUB_I64: 8000000000000000000 - 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' +#endif + +#ifdef SUB_I128 +# ifdef __SIZEOF_INT128__ +  (void)((__uint128_t(1) << 126) - (__uint128_t(1) << 127)); +# else +  puts("__int128 not supported\n"); +# endif +  // CHECK-SUB_I128: {{0x40000000000000000000000000000000 - 0x80000000000000000000000000000000 cannot be represented in type 'unsigned __int128'|__int128 not supported}} +#endif +} 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 000000000000..e916e7fb3c1d --- /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/TestCases/Misc/bounds.cpp b/lib/ubsan/lit_tests/TestCases/Misc/bounds.cpp new file mode 100644 index 000000000000..dc4c4a513c1c --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/bounds.cpp @@ -0,0 +1,15 @@ +// 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 +// RUN: %T/bounds.exe 0 3 0 2>&1 | FileCheck %s --check-prefix=CHECK-B-3 +// RUN: %T/bounds.exe 0 0 4 2>&1 | FileCheck %s --check-prefix=CHECK-C-4 + +int main(int argc, char **argv) { +  int arr[2][3][4] = {}; + +  return arr[argv[1][0] - '0'][argv[2][0] - '0'][argv[3][0] - '0']; +  // CHECK-A-2: bounds.cpp:11:10: runtime error: index 2 out of bounds for type 'int [2][3][4]' +  // CHECK-B-3: bounds.cpp:11:10: runtime error: index 3 out of bounds for type 'int [3][4]' +  // CHECK-C-4: bounds.cpp:11:10: runtime error: index 4 out of bounds for type 'int [4]' +} diff --git a/lib/ubsan/lit_tests/TestCases/Misc/deduplication.cpp b/lib/ubsan/lit_tests/TestCases/Misc/deduplication.cpp new file mode 100644 index 000000000000..d325bf6dd899 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/deduplication.cpp @@ -0,0 +1,25 @@ +// 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> + +void overflow() { +  int i = INT_MIN; +  --i; +} + +int main() { +  // CHECK: Start +  fprintf(stderr, "Start\n"); + +  // CHECK: runtime error +  // CHECK-NOT: runtime error +  // CHECK-NOT: runtime error +  overflow(); +  overflow(); +  overflow(); + +  // CHECK: End +  fprintf(stderr, "End\n"); +  return 0; +} diff --git a/lib/ubsan/lit_tests/TestCases/Misc/enum.cpp b/lib/ubsan/lit_tests/TestCases/Misc/enum.cpp new file mode 100644 index 000000000000..c5642507ad42 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/enum.cpp @@ -0,0 +1,17 @@ +// 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 + +int main(int argc, char **argv) { +  // memset(&e, 0xff, sizeof(e)); +  for (unsigned char *p = (unsigned char*)&e; p != (unsigned char*)(&e + 1); ++p) +    *p = 0xff; + +  // CHECK-PLAIN: error: load of value 4294967295, which is not a valid value for type 'enum E' +  // FIXME: Support marshalling and display of enum class values. +  // CHECK-BOOL: error: load of value <unknown>, which is not a valid value for type 'enum E' +  return (int)e != -1; +} diff --git a/lib/ubsan/lit_tests/TestCases/Misc/missing_return.cpp b/lib/ubsan/lit_tests/TestCases/Misc/missing_return.cpp new file mode 100644 index 000000000000..7da238e25dca --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/missing_return.cpp @@ -0,0 +1,9 @@ +// 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() { +} + +int main(int, char **argv) { +  return f(); +} diff --git a/lib/ubsan/lit_tests/TestCases/Misc/unreachable.cpp b/lib/ubsan/lit_tests/TestCases/Misc/unreachable.cpp new file mode 100644 index 000000000000..75fc3e5bd9a6 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/unreachable.cpp @@ -0,0 +1,6 @@ +// 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 +  __builtin_unreachable(); +} diff --git a/lib/ubsan/lit_tests/TestCases/Misc/vla.c b/lib/ubsan/lit_tests/TestCases/Misc/vla.c new file mode 100644 index 000000000000..2fa88addc0d3 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/Misc/vla.c @@ -0,0 +1,11 @@ +// RUN: %clang -fsanitize=vla-bound %s -O3 -o %t +// RUN: %t 2>&1 | FileCheck %s --check-prefix=CHECK-MINUS-ONE +// RUN: %t a 2>&1 | FileCheck %s --check-prefix=CHECK-ZERO +// RUN: %t a b + +int main(int argc, char **argv) { +  // CHECK-MINUS-ONE: vla.c:9:11: runtime error: variable length array bound evaluates to non-positive value -1 +  // CHECK-ZERO: vla.c:9:11: runtime error: variable length array bound evaluates to non-positive value 0 +  int arr[argc - 2]; +  return 0; +} 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 000000000000..8106ae47ee4f --- /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 000000000000..27c61a34387c --- /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/TestCases/TypeCheck/misaligned.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/misaligned.cpp new file mode 100644 index 000000000000..9b0b9a1197c0 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/misaligned.cpp @@ -0,0 +1,73 @@ +// 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 +// RUN: %t r1 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE +// RUN: %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER +// RUN: %t f1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN +// RUN: %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW + +#include <new> + +struct S { +  S() {} +  int f() { return 0; } +  int k; +}; + +int main(int, char **argv) { +  char c[] __attribute__((aligned(8))) = { 0, 0, 0, 0, 1, 2, 3, 4, 5 }; + +  // Pointer value may be unspecified here, but behavior is not undefined. +  int *p = (int*)&c[4 + argv[1][1] - '0']; +  S *s = (S*)p; + +  (void)*p; // ok! + +  switch (argv[1][0]) { +  case 'l': +    // CHECK-LOAD: misaligned.cpp:[[@LINE+4]]:12: runtime error: load of misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment +    // CHECK-LOAD-NEXT: [[PTR]]: note: pointer points here +    // CHECK-LOAD-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-LOAD-NEXT: {{^             \^}} +    return *p && 0; + +  case 's': +    // CHECK-STORE: misaligned.cpp:[[@LINE+4]]:5: runtime error: store to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment +    // CHECK-STORE-NEXT: [[PTR]]: note: pointer points here +    // CHECK-STORE-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-STORE-NEXT: {{^             \^}} +    *p = 1; +    break; + +  case 'r': +    // CHECK-REFERENCE: misaligned.cpp:[[@LINE+4]]:15: runtime error: reference binding to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment +    // CHECK-REFERENCE-NEXT: [[PTR]]: note: pointer points here +    // CHECK-REFERENCE-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-REFERENCE-NEXT: {{^             \^}} +    {int &r = *p;} +    break; + +  case 'm': +    // CHECK-MEMBER: misaligned.cpp:[[@LINE+4]]:15: runtime error: member access within misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment +    // CHECK-MEMBER-NEXT: [[PTR]]: note: pointer points here +    // CHECK-MEMBER-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-MEMBER-NEXT: {{^             \^}} +    return s->k && 0; + +  case 'f': +    // CHECK-MEMFUN: misaligned.cpp:[[@LINE+4]]:12: runtime error: member call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment +    // CHECK-MEMFUN-NEXT: [[PTR]]: note: pointer points here +    // CHECK-MEMFUN-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-MEMFUN-NEXT: {{^             \^}} +    return s->f() && 0; + +  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-NEXT: [[PTR]]: note: pointer points here +    // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04  05}} +    // CHECK-NEW-NEXT: {{^             \^}} +    return (new (s) S)->k && 0; +  } +} diff --git a/lib/ubsan/lit_tests/TestCases/TypeCheck/null.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/null.cpp new file mode 100644 index 000000000000..79726924d213 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/null.cpp @@ -0,0 +1,38 @@ +// 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 +// RUN: %t m 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER +// RUN: %t f 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN + +struct S { +  int f() { return 0; } +  int k; +}; + +int main(int, char **argv) { +  int *p = 0; +  S *s = 0; + +  (void)*p; // ok! + +  switch (argv[1][0]) { +  case 'l': +    // CHECK-LOAD: null.cpp:22:12: runtime error: load of null pointer of type 'int' +    return *p; +  case 's': +    // CHECK-STORE: null.cpp:25:5: runtime error: store to null pointer of type 'int' +    *p = 1; +    break; +  case 'r': +    // CHECK-REFERENCE: null.cpp:29:15: runtime error: reference binding to null pointer of type 'int' +    {int &r = *p;} +    break; +  case 'm': +    // CHECK-MEMBER: null.cpp:33:15: runtime error: member access within null pointer of type 'S' +    return s->k; +  case 'f': +    // CHECK-MEMFUN: null.cpp:36:12: runtime error: member call on null pointer of type 'S' +    return s->f(); +  } +} diff --git a/lib/ubsan/lit_tests/TestCases/TypeCheck/vptr.cpp b/lib/ubsan/lit_tests/TestCases/TypeCheck/vptr.cpp new file mode 100644 index 000000000000..9095f7279a66 --- /dev/null +++ b/lib/ubsan/lit_tests/TestCases/TypeCheck/vptr.cpp @@ -0,0 +1,117 @@ +// 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 +// RUN: %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace +// RUN: %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace +// RUN: %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace +// RUN: %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace +// RUN: %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace +// RUN: %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace +// RUN: %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace +// RUN: %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace + +// FIXME: This test produces linker errors on Darwin. +// XFAIL: darwin + +struct S { +  S() : a(0) {} +  ~S() {} +  int a; +  int f() { return 0; } +  virtual int v() { return 0; } +}; + +struct T : S { +  T() : b(0) {} +  int b; +  int g() { return 0; } +  virtual int v() { return 1; } +}; + +struct U : S, T { virtual int v() { return 2; } }; + +int main(int, char **argv) { +  T t; +  (void)t.a; +  (void)t.b; +  (void)t.f(); +  (void)t.g(); +  (void)t.v(); +  (void)t.S::v(); + +  U u; +  (void)u.T::a; +  (void)u.b; +  (void)u.T::f(); +  (void)u.g(); +  (void)u.v(); +  (void)u.T::v(); +  (void)((T&)u).S::v(); + +  T *p = 0; +  char Buffer[sizeof(U)] = {}; +  switch (argv[1][1]) { +  case '0': +    p = reinterpret_cast<T*>(Buffer); +    break; +  case 'S': +    p = reinterpret_cast<T*>(new S); +    break; +  case 'T': +    p = new T; +    break; +  case 'U': +    p = new U; +    break; +  case 'V': +    p = reinterpret_cast<T*>(new U); +    break; +  } + +  switch (argv[1][0]) { +  case 'r': +    // Binding a reference to storage of appropriate size and alignment is OK. +    {T &r = *p;} +    break; + +  case 'm': +    // CHECK-MEMBER: vptr.cpp:[[@LINE+5]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T' +    // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']] +    // CHECK-MEMBER-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }} +    // CHECK-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}} +    // CHECK-MEMBER-NEXT: {{^              vptr for}} [[DYN_TYPE]] +    return p->b; + +    // CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T' +    // CHECK-NULL-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr +    // CHECK-NULL-MEMBER-NEXT: {{^ .. .. .. ..  00 00 00 00 00 00 00 00  }} +    // CHECK-NULL-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}} +    // CHECK-NULL-MEMBER-NEXT: {{^              invalid vptr}} + +  case 'f': +    // CHECK-MEMFUN: 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 'T' +    // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']] +    // CHECK-MEMFUN-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }} +    // CHECK-MEMFUN-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}} +    // CHECK-MEMFUN-NEXT: {{^              vptr for}} [[DYN_TYPE]] +    return p->g(); + +  case 'o': +    // 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: {{^                                       (                         )?vptr for}} 'T' base class of [[DYN_TYPE]] +    return reinterpret_cast<U*>(p)->v() - 2; + +  case 'c': +    // CHECK-DOWNCAST: vptr.cpp:[[@LINE+5]]:5: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T' +    // CHECK-DOWNCAST-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']] +    // CHECK-DOWNCAST-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }} +    // CHECK-DOWNCAST-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}} +    // CHECK-DOWNCAST-NEXT: {{^              vptr for}} [[DYN_TYPE]] +    static_cast<T*>(reinterpret_cast<S*>(p)); +    return 0; +  } +}  | 
