ubsan: Support unsigned overflows, and divide-by-zero int/float split.

llvm-svn: 168700
This commit is contained in:
Will Dietz 2012-11-27 15:01:43 +00:00
parent b7029398f3
commit 2631aaf939
7 changed files with 103 additions and 14 deletions

View File

@ -1,7 +1,7 @@
// RUN: %clang -fsanitize=divide-by-zero -DDIVIDEND=0 %s -o %t && %t 2>&1 | FileCheck %s
// RUN: %clang -fsanitize=divide-by-zero -DDIVIDEND=1U %s -o %t && %t 2>&1 | FileCheck %s
// RUN: %clang -fsanitize=divide-by-zero -DDIVIDEND=1.5 %s -o %t && %t 2>&1 | FileCheck %s
// RUN: %clang -fsanitize=divide-by-zero -DDIVIDEND='__int128(123)' %s -o %t && %t 2>&1 | FileCheck %s
// 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='__int128(123)' %s -o %t && %t 2>&1 | FileCheck %s
int main() {
// CHECK: div-zero.cpp:8:12: fatal error: division by zero

View File

@ -0,0 +1,27 @@
// 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
#include <stdint.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:14:5: fatal error: unsigned integer overflow: 2271560481 + 3989547399 cannot be represented in type 'uint32_t' (aka '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'
#endif
#ifdef ADD_I128
(void)((__uint128_t(1) << 127) + (__uint128_t(1) << 127));
// CHECK-ADD_I128: 0x80000000000000000000000000000000 + 0x80000000000000000000000000000000 cannot be represented in type 'unsigned __int128'
#endif
}

View File

@ -0,0 +1,16 @@
// 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: fatal error: unsigned integer overflow: 4294967295 + 1 cannot be represented in type 'unsigned int'
// CHECK-DEC: uincdec-overflow.cpp:15:3: fatal error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
OP;
}

View File

@ -0,0 +1,19 @@
// RUN: %clang -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: fatal error: unsigned integer overflow: 4294967295 * 2 cannot be represented in type 'unsigned int'
return 0;
}

View File

@ -0,0 +1,26 @@
// 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
#include <stdint.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:13:22: fatal 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'
#endif
#ifdef SUB_I128
(void)((__uint128_t(1) << 126) - (__uint128_t(1) << 127));
// CHECK-SUB_I128: 0x40000000000000000000000000000000 - 0x80000000000000000000000000000000 cannot be represented in type 'unsigned __int128'
#endif
}

View File

@ -43,30 +43,31 @@ void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
Die();
}
/// \brief Common diagnostic emission for various forms of signed overflow.
template<typename T> static void HandleSignedOverflow(OverflowData *Data,
/// \brief Common diagnostic emission for various forms of integer overflow.
template<typename T> static void HandleIntegerOverflow(OverflowData *Data,
ValueHandle LHS,
const char *Operator,
T RHS) {
Diag(Data->Loc, "signed integer overflow: "
"%0 %1 %2 cannot be represented in type %3")
Diag(Data->Loc, "%0 integer overflow: "
"%1 %2 %3 cannot be represented in type %4")
<< (Data->Type.isSignedIntegerTy() ? "signed" : "unsigned")
<< Value(Data->Type, LHS) << Operator << RHS << Data->Type;
Die();
}
void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data,
ValueHandle LHS, ValueHandle RHS) {
HandleSignedOverflow(Data, LHS, "+", Value(Data->Type, RHS));
HandleIntegerOverflow(Data, LHS, "+", Value(Data->Type, RHS));
}
void __ubsan::__ubsan_handle_sub_overflow(OverflowData *Data,
ValueHandle LHS, ValueHandle RHS) {
HandleSignedOverflow(Data, LHS, "-", Value(Data->Type, RHS));
HandleIntegerOverflow(Data, LHS, "-", Value(Data->Type, RHS));
}
void __ubsan::__ubsan_handle_mul_overflow(OverflowData *Data,
ValueHandle LHS, ValueHandle RHS) {
HandleSignedOverflow(Data, LHS, "*", Value(Data->Type, RHS));
HandleIntegerOverflow(Data, LHS, "*", Value(Data->Type, RHS));
}
void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,

View File

@ -35,15 +35,15 @@ struct OverflowData {
const TypeDescriptor &Type;
};
/// \brief Handle a signed integer addition overflow.
/// \brief Handle an integer addition overflow.
extern "C" void __ubsan_handle_add_overflow(OverflowData *Data,
ValueHandle LHS,
ValueHandle RHS);
/// \brief Handle a signed integer subtraction overflow.
/// \brief Handle an integer subtraction overflow.
extern "C" void __ubsan_handle_sub_overflow(OverflowData *Data,
ValueHandle LHS,
ValueHandle RHS);
/// \brief Handle a signed integer multiplication overflow.
/// \brief Handle an integer multiplication overflow.
extern "C" void __ubsan_handle_mul_overflow(OverflowData *Data,
ValueHandle LHS,
ValueHandle RHS);