blob: acef4b34fb09f3fde1aa7fc558925d39e7310f69 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
// RUN: %clang_analyze_cc1 -fblocks \
// RUN: -analyzer-checker=core \
// RUN: -analyzer-checker=osx.cocoa.MissingSuperCall \
// RUN: -analyzer-checker=osx.cocoa.NSError \
// RUN: -analyzer-checker=osx.ObjCProperty \
// RUN: -analyzer-checker=osx.cocoa.RetainCount \
// RUN: -analyzer-checker=unix.Malloc \
// RUN: -analyzer-checker=alpha.core.CastToStruct \
// RUN: -Wno-unused-value -Wno-objc-root-class -verify %s
#define SUPPRESS __attribute__((suppress))
#define SUPPRESS_SPECIFIC(...) __attribute__((suppress(__VA_ARGS__)))
@protocol NSObject
- (id)retain;
- (oneway void)release;
@end
@interface NSObject <NSObject> {
}
- (id)init;
+ (id)alloc;
@end
typedef int NSInteger;
typedef char BOOL;
typedef struct _NSZone NSZone;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
@end
@class NSDictionary;
@interface NSError : NSObject <NSCopying, NSCoding> {
}
+ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict;
@end
@interface NSMutableString : NSObject
@end
typedef __typeof__(sizeof(int)) size_t;
void *malloc(size_t);
void free(void *);
void dereference_1() {
int *x = 0;
*x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
void dereference_suppression_1() {
int *x = 0;
SUPPRESS { *x; } // no-warning
}
void dereference_2() {
int *x = 0;
if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
}
void dereference_suppression_2() {
int *x = 0;
SUPPRESS if (*x) { // no-warning
}
}
void dereference_suppression_2a() {
int *x = 0;
// FIXME: Implement suppressing individual checkers.
SUPPRESS_SPECIFIC("core.NullDereference") if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
}
void dereference_suppression_2b() {
int *x = 0;
// This is not a MallocChecker issue so it shouldn't be suppressed. (Though the attribute
// doesn't really understand any of those arguments yet.)
SUPPRESS_SPECIFIC("unix.Malloc") if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
}
void dereference_3(int cond) {
int *x = 0;
if (cond) {
(*x)++; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
}
void dereference_suppression_3(int cond) {
int *x = 0;
SUPPRESS if (cond) {
(*x)++; // no-warning
}
}
void dereference_4() {
int *x = 0;
int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
void dereference_suppression_4() {
int *x = 0;
SUPPRESS int y = *x; // no-warning
}
void dereference_5() {
int *x = 0;
int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
int z = *x; // no-warning (duplicate)
}
void dereference_suppression_5_1() {
int *x = 0;
SUPPRESS int y = *x; // no-warning
int z = *x; // no-warning (duplicate)
}
void dereference_suppression_5_2() {
int *x = 0;
int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
SUPPRESS int z = *x; // no-warning
}
void do_deref(int *y) {
*y = 1; // expected-warning{{Dereference of null pointer (loaded from variable 'y')}}
}
void dereference_interprocedural() {
int *x = 0;
do_deref(x);
}
void do_deref_suppressed(int *y) {
SUPPRESS *y = 1; // no-warning
}
void dereference_interprocedural_suppressed() {
int *x = 0;
do_deref_suppressed(x);
}
int malloc_leak_1() {
int *x = (int *)malloc(sizeof(int));
*x = 42;
return *x; // expected-warning{{Potential leak of memory pointed to by 'x'}}
}
int malloc_leak_suppression_1_1() {
SUPPRESS int *x = (int *)malloc(sizeof(int));
*x = 42;
return *x;
}
int malloc_leak_suppression_1_2() {
int *x = (int *)malloc(sizeof(int));
*x = 42;
SUPPRESS return *x;
}
void malloc_leak_2() {
int *x = (int *)malloc(sizeof(int));
*x = 42;
} // expected-warning{{Potential leak of memory pointed to by 'x'}}
void malloc_leak_suppression_2_1() {
SUPPRESS int *x = (int *)malloc(sizeof(int));
*x = 42;
}
void malloc_leak_suppression_2_2() SUPPRESS {
int *x = (int *)malloc(sizeof(int));
*x = 42;
} // no-warning
SUPPRESS void malloc_leak_suppression_2_3() {
int *x = (int *)malloc(sizeof(int));
*x = 42;
} // no-warning
void malloc_leak_suppression_2_4(int cond) {
int *x = (int *)malloc(sizeof(int));
*x = 42;
SUPPRESS;
// FIXME: The warning should be suppressed but dead symbol elimination
// happens too late.
} // expected-warning{{Potential leak of memory pointed to by 'x'}}
void retain_release_leak_1() {
[[NSMutableString alloc] init]; // expected-warning{{Potential leak of an object of type 'NSMutableString *'}}
}
void retain_release_leak_suppression_1() {
SUPPRESS { [[NSMutableString alloc] init]; }
}
void retain_release_leak_2(int cond) {
id obj = [[NSMutableString alloc] init]; // expected-warning{{Potential leak of an object stored into 'obj'}}
if (cond) {
[obj release];
}
}
void retain_release_leak__suppression_2(int cond) {
SUPPRESS id obj = [[NSMutableString alloc] init];
if (cond) {
[obj release];
}
}
@interface UIResponder : NSObject {
}
- (char)resignFirstResponder;
@end
@interface Test : UIResponder {
}
@property(copy) NSMutableString *mutableStr;
// expected-warning@-1 {{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
@end
@implementation Test
- (BOOL)resignFirstResponder {
return 0;
} // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'Test' is missing a [super resignFirstResponder] call}}
- (void)methodWhichMayFail:(NSError **)error {
// expected-warning@-1 {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred}}
}
@end
@interface TestSuppress : UIResponder {
}
@property(copy) SUPPRESS NSMutableString *mutableStr; // no-warning
@end
@implementation TestSuppress
- (BOOL)resignFirstResponder SUPPRESS { // no-warning
return 0;
}
- (void)methodWhichMayFail:(NSError **)error SUPPRESS { // no-warning
}
@end
struct AB {
int A, B;
};
struct ABC {
int A, B, C;
};
void ast_checker_1() {
struct AB Ab;
struct ABC *Abc;
Abc = (struct ABC *)&Ab; // expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
}
void ast_checker_suppress_1() {
struct AB Ab;
struct ABC *Abc;
SUPPRESS { Abc = (struct ABC *)&Ab; }
}
SUPPRESS int suppressed_function() {
int *x = 0;
return *x; // no-warning
}
SUPPRESS int suppressed_function_forward();
int suppressed_function_forward() {
int *x = 0;
return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
int suppressed_function_backward();
SUPPRESS int suppressed_function_backward() {
int *x = 0;
return *x; // no-warning
}
SUPPRESS
@interface SuppressedInterface
-(int)suppressedMethod;
-(int)regularMethod SUPPRESS;
@end
@implementation SuppressedInterface
-(int)suppressedMethod SUPPRESS {
int *x = 0;
return *x; // no-warning
}
// This one is NOT suppressed by the attribute on the forward declaration,
// and it's also NOT suppressed by the attribute on the entire interface.
-(int)regularMethod {
int *x = 0;
return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
}
@end
|