llvm-project

Форк
0
/
ubsan-nullability.m 
226 строк · 8.8 Кб
1
// REQUIRES: asserts
2
// RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
3
// RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
4

5
// CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6
6
// CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23
7
// CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9
8
// CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10
9
// CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 506, i32 10
10
// CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25
11
// CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26
12
// CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29
13
// CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 800, i32 6
14

15
#define NULL ((void *)0)
16
#define INULL ((int *)NULL)
17
#define INNULL ((int *_Nonnull)NULL)
18

19
// CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval1
20
#line 100
21
int *_Nonnull nonnull_retval1(int *p) {
22
  // CHECK: nullcheck:
23
  // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
24
  // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
25
  // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]]
26
  return p;
27
  // CHECK: ret ptr
28
}
29

30
#line 190
31
void nonnull_arg(int *_Nonnull p) {}
32

33
// CHECK-LABEL: define{{.*}} void @{{.*}}call_func_with_nonnull_arg
34
#line 200
35
void call_func_with_nonnull_arg(int *_Nonnull p) {
36
  // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
37
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
38
  // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]]
39
  nonnull_arg(p);
40
}
41

42
// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign1
43
#line 300
44
void nonnull_assign1(int *p) {
45
  // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
46
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
47
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]]
48
  int *_Nonnull local;
49
  local = p;
50
}
51

52
// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign2
53
#line 400
54
void nonnull_assign2(int *p) {
55
  // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
56
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
57
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]]
58
  int *_Nonnull arr[1];
59
  arr[0] = p;
60
}
61

62
struct S1 {
63
  int *_Nonnull mptr;
64
};
65

66
// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign3
67
#line 500
68
void nonnull_assign3(int *p) {
69
  // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
70
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
71
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]]
72
  // CHECK-NOT: call void @__ubsan_handle_type_mismatch
73
  struct S1 s;
74
  s.mptr = p;
75
}
76

77
// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init1
78
#line 600
79
void nonnull_init1(int *p) {
80
  // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
81
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
82
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]]
83
  int *_Nonnull local = p;
84
}
85

86
// CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init2
87
#line 700
88
void nonnull_init2(int *p) {
89
  // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
90
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
91
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]]
92
  // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize
93
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
94
  // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]]
95
  int *_Nonnull arr[] = {p, p};
96
}
97

98
// CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval2
99
#line 800
100
int *_Nonnull nonnull_retval2(int *_Nonnull arg1,  //< Test this.
101
                              int *_Nonnull arg2,  //< Test this.
102
                              int *_Nullable arg3, //< Don't test the rest.
103
                              int *arg4,
104
                              int arg5, ...) {
105
  // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
106
  // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize
107
  // CHECK: [[ARG2CMP:%.*]] = icmp ne ptr %arg2, null, !nosanitize
108
  // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]]
109
  // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
110
  // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
111
  // CHECK-NEXT: [[DO_RV_CHECK_3:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK_2]]
112
  // CHECK: br i1 [[DO_RV_CHECK_3]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
113
  // CHECK: [[NULL]]:
114
  // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
115
  // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
116
  // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]]
117
  return arg1;
118
  // CHECK: [[NONULL]]:
119
  // CHECK-NEXT: ret ptr
120
}
121

122
@interface A
123
+(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1;
124
-(int *_Nonnull) objc_method: (int *_Nonnull) arg1;
125
@end
126

127
@implementation A
128

129
// CHECK-LABEL: define internal ptr @"\01+[A objc_clsmethod:]"
130
+(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 {
131
  // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
132
  // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
133
  // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
134
  // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
135
  // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]]
136
  // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
137
  // CHECK: [[NULL]]:
138
  // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
139
  // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
140
  // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
141
  return arg1;
142
  // CHECK: [[NONULL]]:
143
  // CHECK-NEXT: ret ptr
144
}
145

146
// CHECK-LABEL: define internal ptr @"\01-[A objc_method:]"
147
-(int *_Nonnull) objc_method: (int *_Nonnull) arg1 {
148
  // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize
149
  // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
150
  // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr
151
  // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null
152
  // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]]
153
  // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
154
  // CHECK: [[NULL]]:
155
  // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize
156
  // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
157
  // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
158
  return arg1;
159
  // CHECK: [[NONULL]]:
160
  // CHECK-NEXT: ret ptr
161
}
162
@end
163

164
// CHECK-LABEL: define{{.*}} void @{{.*}}call_A
165
void call_A(A *a, int *p) {
166
  // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P1:%.*]], null, !nosanitize
167
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
168
  // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
169
  // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P1]])
170
  [a objc_method: p];
171

172
  // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P2:%.*]], null, !nosanitize
173
  // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
174
  // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
175
  // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P2]])
176
  [A objc_clsmethod: p];
177
}
178

179
void dont_crash(int *_Nonnull p, ...) {}
180

181
@protocol NSObject
182
- (id)init;
183
@end
184
@interface NSObject <NSObject> {}
185
@end
186

187
#pragma clang assume_nonnull begin
188

189
/// Create a "NSObject * _Nonnull" instance.
190
NSObject *get_nonnull_error(void) {
191
  // Use nil for convenience. The actual object doesn't matter.
192
  return (NSObject *)NULL;
193
}
194

195
NSObject *_Nullable no_null_return_value_diagnostic(int flag) {
196
// CHECK-LABEL: define internal {{.*}}no_null_return_value_diagnostic{{i?}}_block_invoke
197
// CHECK-NOT: @__ubsan_handle_nullability_return
198
  NSObject *_Nullable (^foo)(void) = ^(void) {
199
    if (flag) {
200
      // Clang should not infer a nonnull return value for this block when this
201
      // call is present.
202
      return get_nonnull_error();
203
    } else {
204
      return (NSObject *)NULL;
205
    }
206
  };
207
  return foo();
208
}
209

210
#pragma clang assume_nonnull end
211

212
int main(void) {
213
  nonnull_retval1(INULL);
214
  nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0);
215
  call_func_with_nonnull_arg(INNULL);
216
  nonnull_assign1(INULL);
217
  nonnull_assign2(INULL);
218
  nonnull_assign3(INULL);
219
  nonnull_init1(INULL);
220
  nonnull_init2(INULL);
221
  call_A((A *)NULL, INULL);
222
  dont_crash(INNULL, NULL);
223
  no_null_return_value_diagnostic(0);
224
  no_null_return_value_diagnostic(1);
225
  return 0;
226
}
227

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.