Clang Project

clang_source_code/test/CodeGen/catch-implicit-signed-integer-truncation-or-sign-change.c
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:.*]])
19signed 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
52unsigned_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
82unsigned_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
112unsigned_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
143unsigned_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}
153