Roman Lebedev | 62debd80 | 2018-10-30 21:58:56 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK |
| 2 | // RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fno-sanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE |
| 3 | // RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER |
| 4 | // RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-trap=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE |
| 5 | |
| 6 | // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" } |
| 7 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" } |
| 8 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 4 } |
| 9 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_200_SIGN_CHANGE:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 } |
| 10 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_300_SIGN_CHANGE:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 3 } |
| 11 | // CHECK-SANITIZE-ANYRECOVER-NEXT: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 } |
| 12 | |
| 13 | //============================================================================// |
| 14 | // Both sanitizers are enabled, and not disabled per-function. |
| 15 | //============================================================================// |
| 16 | |
| 17 | // CHECK-LABEL: @unsigned_int_to_signed_char |
| 18 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 19 | signed char unsigned_int_to_signed_char(unsigned int src) { |
| 20 | // CHECK-NEXT: [[ENTRY:.*]]: |
| 21 | // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32 |
| 22 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 23 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 24 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 25 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize |
| 26 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 27 | // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[CONV]] to i32, !nosanitize |
| 28 | // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[DST]], !nosanitize |
| 29 | // CHECK-SANITIZE-NEXT: %[[BOTHCHECKS:.*]] = and i1 %[[SIGNCHANGECHECK]], %[[TRUNCHECK]], !nosanitize |
| 30 | // CHECK-SANITIZE-NEXT: br i1 %[[BOTHCHECKS]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 31 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 32 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 33 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 34 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 35 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_SIGNED_TRUNCATION_OR_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 36 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 37 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 38 | // CHECK-SANITIZE: [[CONT]]: |
| 39 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 40 | // CHECK-NEXT: } |
| 41 | #line 100 |
| 42 | return src; |
| 43 | } |
| 44 | |
| 45 | //============================================================================// |
| 46 | // Truncation sanitizer is disabled per-function. |
| 47 | //============================================================================// |
| 48 | |
| 49 | // CHECK-LABEL: @unsigned_int_to_signed_char__no_truncation_sanitizer |
| 50 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 51 | __attribute__((no_sanitize("implicit-integer-truncation"))) signed char |
| 52 | unsigned_int_to_signed_char__no_truncation_sanitizer(unsigned int src) { |
| 53 | // CHECK-NEXT: [[ENTRY:.*]]: |
| 54 | // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32 |
| 55 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 56 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 57 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 58 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize |
| 59 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 60 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 61 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 62 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 63 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 64 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 65 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 66 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 67 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 68 | // CHECK-SANITIZE: [[CONT]]: |
| 69 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 70 | // CHECK-NEXT: } |
| 71 | #line 200 |
| 72 | return src; |
| 73 | } |
| 74 | |
| 75 | //============================================================================// |
| 76 | // Signed truncation sanitizer is disabled per-function. |
| 77 | //============================================================================// |
| 78 | |
| 79 | // CHECK-LABEL: @unsigned_int_to_signed_char__no_signed_truncation_sanitizer |
| 80 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 81 | __attribute__((no_sanitize("implicit-signed-integer-truncation"))) signed char |
| 82 | unsigned_int_to_signed_char__no_signed_truncation_sanitizer(unsigned int src) { |
| 83 | // CHECK-NEXT: [[ENTRY:.*]]: |
| 84 | // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32 |
| 85 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 86 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 87 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 88 | // CHECK-SANITIZE-NEXT: %[[DST_NEGATIVITYCHECK:.*]] = icmp slt i8 %[[CONV]], 0, !nosanitize |
| 89 | // CHECK-SANITIZE-NEXT: %[[SIGNCHANGECHECK:.*]] = icmp eq i1 false, %[[DST_NEGATIVITYCHECK]], !nosanitize |
| 90 | // CHECK-SANITIZE-NEXT: br i1 %[[SIGNCHANGECHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 91 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 92 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 93 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 94 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 95 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGN_CHANGE]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 96 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 97 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 98 | // CHECK-SANITIZE: [[CONT]]: |
| 99 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 100 | // CHECK-NEXT: } |
| 101 | #line 300 |
| 102 | return src; |
| 103 | } |
| 104 | |
| 105 | //============================================================================// |
| 106 | // Sign change sanitizer is disabled per-function |
| 107 | //============================================================================// |
| 108 | |
| 109 | // CHECK-LABEL: @unsigned_int_to_signed_char__no_sign_change_sanitizer |
| 110 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 111 | __attribute__((no_sanitize("implicit-integer-sign-change"))) signed char |
| 112 | unsigned_int_to_signed_char__no_sign_change_sanitizer(unsigned int src) { |
| 113 | // CHECK-NEXT: [[ENTRY:.*]]: |
| 114 | // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32 |
| 115 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 116 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 117 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 118 | // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[CONV]] to i32, !nosanitize |
| 119 | // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[DST]], !nosanitize |
| 120 | // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize |
| 121 | // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]: |
| 122 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[DST]] to i64, !nosanitize |
| 123 | // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTCONV:.*]] = zext i8 %[[CONV]] to i64, !nosanitize |
| 124 | // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 125 | // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTCONV]]){{.*}}, !nosanitize |
| 126 | // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize |
| 127 | // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize |
| 128 | // CHECK-SANITIZE: [[CONT]]: |
| 129 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 130 | // CHECK-NEXT: } |
| 131 | #line 400 |
| 132 | return src; |
| 133 | } |
| 134 | |
| 135 | //============================================================================// |
| 136 | // Both sanitizers are disabled per-function. |
| 137 | //============================================================================// |
| 138 | |
| 139 | // CHECK-LABEL: @unsigned_int_to_signed_char__no_sanitizers |
| 140 | // CHECK-SAME: (i32 %[[SRC:.*]]) |
| 141 | __attribute__((no_sanitize("implicit-integer-truncation"), |
| 142 | no_sanitize("implicit-integer-sign-change"))) signed char |
| 143 | unsigned_int_to_signed_char__no_sanitizers(unsigned int src) { |
| 144 | // CHECK-NEXT: [[ENTRY:.*]]: |
| 145 | // CHECK-NEXT: %[[SRC_ADDR:.*]] = alloca i32 |
| 146 | // CHECK-NEXT: store i32 %[[SRC]], i32* %[[SRC_ADDR]] |
| 147 | // CHECK-NEXT: %[[DST:.*]] = load i32, i32* %[[SRC_ADDR]] |
| 148 | // CHECK-NEXT: %[[CONV:.*]] = trunc i32 %[[DST]] to i8 |
| 149 | // CHECK-NEXT: ret i8 %[[CONV]] |
| 150 | // CHECK-NEXT: } |
| 151 | return src; |
| 152 | } |