blob: b4d53c59de61ef82a139f409c9b5c595f3d7f328 [file] [log] [blame]
Kristof Umann1a170322019-02-05 00:39:33 +00001==================
2Available Checkers
3==================
4
Alexander Kornienko9a857d22019-02-11 15:17:13 +00005The analyzer performs checks that are categorized into families or "checkers".
Kristof Umann1a170322019-02-05 00:39:33 +00006
Alexander Kornienko9a857d22019-02-11 15:17:13 +00007The default set of checkers covers a variety of checks targeted at finding security and API usage bugs,
8dead code, and other logic errors. See the :ref:`default-checkers` checkers list below.
9
Kristof Umann1a170322019-02-05 00:39:33 +000010In addition to these, the analyzer contains a number of :ref:`alpha-checkers` (aka *alpha* checkers).
11These checkers are under development and are switched off by default. They may crash or emit a higher number of false positives.
12
13The :ref:`debug-checkers` package contains checkers for analyzer developers for debugging purposes.
14
15.. contents:: Table of Contents
16 :depth: 4
17
18
19.. _default-checkers:
20
21Default Checkers
22----------------
23
24.. _core-checkers:
25
26core
27^^^^
Alexander Kornienko9a857d22019-02-11 15:17:13 +000028Models core language features and contains general-purpose checkers such as division by zero,
29null pointer dereference, usage of uninitialized values, etc.
Kristof Umann1a170322019-02-05 00:39:33 +000030*These checkers must be always switched on as other checker rely on them.*
31
32core.CallAndMessage (C, C++, ObjC)
33""""""""""""""""""""""""""""""""""
34 Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers).
35
Alexander Kornienko9a857d22019-02-11 15:17:13 +000036.. literalinclude:: checkers/callandmessage_example.c
Kristof Umann1a170322019-02-05 00:39:33 +000037 :language: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +000038
Kristof Umann1a170322019-02-05 00:39:33 +000039core.DivideZero (C, C++, ObjC)
40""""""""""""""""""""""""""""""
41 Check for division by zero.
42
43.. literalinclude:: checkers/dividezero_example.c
44 :language: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +000045
46core.NonNullParamChecker (C, C++, ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +000047"""""""""""""""""""""""""""""""""""""""
48Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute.
49
Alexander Kornienko9a857d22019-02-11 15:17:13 +000050.. code-block:: cpp
51
Kristof Umann1a170322019-02-05 00:39:33 +000052 int f(int *p) __attribute__((nonnull));
Alexander Kornienko9a857d22019-02-11 15:17:13 +000053
Kristof Umann1a170322019-02-05 00:39:33 +000054 void test(int *p) {
55 if (!p)
56 f(p); // warn
57 }
58
59core.NullDereference (C, C++, ObjC)
60"""""""""""""""""""""""""""""""""""
61Check for dereferences of null pointers.
62
63.. code-block:: objc
64
65 // C
66 void test(int *p) {
67 if (p)
68 return;
Alexander Kornienko9a857d22019-02-11 15:17:13 +000069
Kristof Umann1a170322019-02-05 00:39:33 +000070 int x = p[0]; // warn
71 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +000072
Kristof Umann1a170322019-02-05 00:39:33 +000073 // C
74 void test(int *p) {
75 if (!p)
76 *p = 0; // warn
77 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +000078
Kristof Umann1a170322019-02-05 00:39:33 +000079 // C++
80 class C {
81 public:
82 int x;
83 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +000084
Kristof Umann1a170322019-02-05 00:39:33 +000085 void test() {
86 C *pc = 0;
87 int k = pc->x; // warn
88 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +000089
Kristof Umann1a170322019-02-05 00:39:33 +000090 // Objective-C
91 @interface MyClass {
92 @public
93 int x;
94 }
95 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +000096
Kristof Umann1a170322019-02-05 00:39:33 +000097 void test() {
98 MyClass *obj = 0;
99 obj->x = 1; // warn
100 }
101
102core.StackAddressEscape (C)
103"""""""""""""""""""""""""""
104Check that addresses to stack memory do not escape the function.
105
106.. code-block:: c
107
108 char const *p;
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000109
Kristof Umann1a170322019-02-05 00:39:33 +0000110 void test() {
111 char const str[] = "string";
112 p = str; // warn
113 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000114
Kristof Umann1a170322019-02-05 00:39:33 +0000115 void* test() {
116 return __builtin_alloca(12); // warn
117 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000118
Kristof Umann1a170322019-02-05 00:39:33 +0000119 void test() {
120 static int *x;
121 int y;
122 x = &y; // warn
123 }
124
125
126core.UndefinedBinaryOperatorResult (C)
127""""""""""""""""""""""""""""""""""""""
128Check for undefined results of binary operators.
129
130.. code-block:: c
131
132 void test() {
133 int x;
134 int y = x + 1; // warn: left operand is garbage
135 }
136
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000137core.VLASize (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000138""""""""""""""""
139Check for declarations of Variable Length Arrays of undefined or zero size.
140
141 Check for declarations of VLA of undefined or zero size.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000142
Kristof Umann1a170322019-02-05 00:39:33 +0000143.. code-block:: c
144
145 void test() {
146 int x;
147 int vla1[x]; // warn: garbage as size
148 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000149
Kristof Umann1a170322019-02-05 00:39:33 +0000150 void test() {
151 int x = 0;
152 int vla2[x]; // warn: zero size
153 }
154
155core.uninitialized.ArraySubscript (C)
156"""""""""""""""""""""""""""""""""""""
157Check for uninitialized values used as array subscripts.
158
159.. code-block:: c
160
161 void test() {
162 int i, a[10];
163 int x = a[i]; // warn: array subscript is undefined
164 }
165
166core.uninitialized.Assign (C)
167"""""""""""""""""""""""""""""
168Check for assigning uninitialized values.
169
170.. code-block:: c
171
172 void test() {
173 int x;
174 x |= 1; // warn: left expression is uninitialized
175 }
176
177core.uninitialized.Branch (C)
178"""""""""""""""""""""""""""""
179Check for uninitialized values used as branch conditions.
180
181.. code-block:: c
182
183 void test() {
184 int x;
185 if (x) // warn
186 return;
187 }
188
189core.uninitialized.CapturedBlockVariable (C)
190""""""""""""""""""""""""""""""""""""""""""""
191Check for blocks that capture uninitialized values.
192
193.. code-block:: c
194
195 void test() {
196 int x;
197 ^{ int y = x; }(); // warn
198 }
199
200core.uninitialized.UndefReturn (C)
201""""""""""""""""""""""""""""""""""
202Check for uninitialized values being returned to the caller.
203
204.. code-block:: c
205
206 int test() {
207 int x;
208 return x; // warn
209 }
210
211.. _cplusplus-checkers:
212
213
214cpluslus
215^^^^^^^^
216
217C++ Checkers.
218
219cplusplus.InnerPointer
220""""""""""""""""""""""
221Check for inner pointers of C++ containers used after re/deallocation.
222
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000223cplusplus.NewDelete (C++)
Kristof Umann1a170322019-02-05 00:39:33 +0000224"""""""""""""""""""""""""
225Check for double-free and use-after-free problems. Traces memory managed by new/delete.
226
227.. literalinclude:: checkers/newdelete_example.cpp
228 :language: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000229
230cplusplus.NewDeleteLeaks (C++)
Kristof Umann1a170322019-02-05 00:39:33 +0000231""""""""""""""""""""""""""""""
232Check for memory leaks. Traces memory managed by new/delete.
233
234.. code-block:: cpp
235
236 void test() {
237 int *p = new int;
238 } // warn
239
240
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000241cplusplus.SelfAssignment (C++)
Kristof Umann1a170322019-02-05 00:39:33 +0000242""""""""""""""""""""""""""""""
243Checks C++ copy and move assignment operators for self assignment.
244
245.. _deadcode-checkers:
246
247deadcode
248^^^^^^^^
249
250Dead Code Checkers.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000251
252deadcode.DeadStores (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000253"""""""""""""""""""""""
254Check for values stored to variables that are never read afterwards.
255
256.. code-block:: c
257
258 void test() {
259 int x;
260 x = 1; // warn
261 }
262
263.. _nullability-checkers:
264
265nullability
266^^^^^^^^^^^
267
268Objective C checkers that warn for null pointer passing and dereferencing errors.
269
270nullability.NullPassedToNonnull (ObjC)
271""""""""""""""""""""""""""""""""""""""
272Warns when a null pointer is passed to a pointer which has a _Nonnull type.
273
274.. code-block:: objc
275
276 if (name != nil)
277 return;
278 // Warning: nil passed to a callee that requires a non-null 1st parameter
279 NSString *greeting = [@"Hello " stringByAppendingString:name];
280
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000281nullability.NullReturnedFromNonnull (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000282""""""""""""""""""""""""""""""""""""""""""
283Warns when a null pointer is returned from a function that has _Nonnull return type.
284
285.. code-block:: objc
286
287 - (nonnull id)firstChild {
288 id result = nil;
289 if ([_children count] > 0)
290 result = _children[0];
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000291
Kristof Umann1a170322019-02-05 00:39:33 +0000292 // Warning: nil returned from a method that is expected
293 // to return a non-null value
294 return result;
295 }
296
297nullability.NullableDereferenced (ObjC)
298"""""""""""""""""""""""""""""""""""""""
299Warns when a nullable pointer is dereferenced.
300
301.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000302
Kristof Umann1a170322019-02-05 00:39:33 +0000303 struct LinkedList {
304 int data;
305 struct LinkedList *next;
306 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000307
Kristof Umann1a170322019-02-05 00:39:33 +0000308 struct LinkedList * _Nullable getNext(struct LinkedList *l);
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000309
Kristof Umann1a170322019-02-05 00:39:33 +0000310 void updateNextData(struct LinkedList *list, int newData) {
311 struct LinkedList *next = getNext(list);
312 // Warning: Nullable pointer is dereferenced
313 next->data = 7;
314 }
315
316nullability.NullablePassedToNonnull (ObjC)
317""""""""""""""""""""""""""""""""""""""""""
318Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.
319
320.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000321
Kristof Umann1a170322019-02-05 00:39:33 +0000322 typedef struct Dummy { int val; } Dummy;
323 Dummy *_Nullable returnsNullable();
324 void takesNonnull(Dummy *_Nonnull);
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000325
Kristof Umann1a170322019-02-05 00:39:33 +0000326 void test() {
327 Dummy *p = returnsNullable();
328 takesNonnull(p); // warn
329 }
330
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000331nullability.NullableReturnedFromNonnull (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000332""""""""""""""""""""""""""""""""""""""""""""""
333Warns when a nullable pointer is returned from a function that has _Nonnull return type.
334
335.. _optin-checkers:
336
337optin
338^^^^^
339
340Checkers for portability, performance or coding style specific rules.
341
342optin.cplusplus.VirtualCall (C++)
343"""""""""""""""""""""""""""""""""
344Check virtual function calls during construction or destruction.
345
346.. code-block:: cpp
347
348 class A {
349 public:
350 A() {
351 f(); // warn
352 }
353 virtual void f();
354 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000355
Kristof Umann1a170322019-02-05 00:39:33 +0000356 class A {
357 public:
358 ~A() {
359 this->f(); // warn
360 }
361 virtual void f();
362 };
363
364optin.mpi.MPI-Checker (C)
365"""""""""""""""""""""""""
366Checks MPI code.
367
368.. code-block:: c
369
370 void test() {
371 double buf = 0;
372 MPI_Request sendReq1;
373 MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM,
374 0, MPI_COMM_WORLD, &sendReq1);
375 } // warn: request 'sendReq1' has no matching wait.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000376
Kristof Umann1a170322019-02-05 00:39:33 +0000377 void test() {
378 double buf = 0;
379 MPI_Request sendReq;
380 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq);
381 MPI_Irecv(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn
382 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn
383 MPI_Wait(&sendReq, MPI_STATUS_IGNORE);
384 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000385
Kristof Umann1a170322019-02-05 00:39:33 +0000386 void missingNonBlocking() {
387 int rank = 0;
388 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
389 MPI_Request sendReq1[10][10][10];
390 MPI_Wait(&sendReq1[1][7][9], MPI_STATUS_IGNORE); // warn
391 }
392
393optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (ObjC)
394"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
395Check that NSLocalizedString macros include a comment for context.
396
397.. code-block:: objc
398
399 - (void)test {
400 NSString *string = NSLocalizedString(@"LocalizedString", nil); // warn
401 NSString *string2 = NSLocalizedString(@"LocalizedString", @" "); // warn
402 NSString *string3 = NSLocalizedStringWithDefaultValue(
403 @"LocalizedString", nil, [[NSBundle alloc] init], nil,@""); // warn
404 }
405
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000406optin.osx.cocoa.localizability.NonLocalizedStringChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000407"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
408Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings.
409
410.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000411
Kristof Umann1a170322019-02-05 00:39:33 +0000412 NSString *alarmText =
413 NSLocalizedString(@"Enabled", @"Indicates alarm is turned on");
414 if (!isEnabled) {
415 alarmText = @"Disabled";
416 }
417 UILabel *alarmStateLabel = [[UILabel alloc] init];
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000418
Kristof Umann1a170322019-02-05 00:39:33 +0000419 // Warning: User-facing text should use localized string macro
420 [alarmStateLabel setText:alarmText];
421
422optin.performance.GCDAntipattern
423""""""""""""""""""""""""""""""""
424Check for performance anti-patterns when using Grand Central Dispatch.
425
426optin.performance.Padding
427"""""""""""""""""""""""""
428Check for excessively padded structs.
429
430optin.portability.UnixAPI
431"""""""""""""""""""""""""
432Finds implementation-defined behavior in UNIX/Posix functions.
433
434
435.. _security-checkers:
436
437security
438^^^^^^^^
439
440Security related checkers.
441
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000442security.FloatLoopCounter (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000443"""""""""""""""""""""""""""""
444Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP).
445
446.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000447
Kristof Umann1a170322019-02-05 00:39:33 +0000448 void test() {
449 for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // warn
450 }
451
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000452security.insecureAPI.UncheckedReturn (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000453""""""""""""""""""""""""""""""""""""""""
454Warn on uses of functions whose return values must be always checked.
455
456.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000457
Kristof Umann1a170322019-02-05 00:39:33 +0000458 void test() {
459 setuid(1); // warn
460 }
461
462security.insecureAPI.bcmp (C)
463"""""""""""""""""""""""""""""
464Warn on uses of the 'bcmp' function.
465
466.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000467
Kristof Umann1a170322019-02-05 00:39:33 +0000468 void test() {
469 bcmp(ptr0, ptr1, n); // warn
470 }
471
472security.insecureAPI.bcopy (C)
473""""""""""""""""""""""""""""""
474Warn on uses of the 'bcopy' function.
475
476.. code-block:: c
477
478 void test() {
479 bcopy(src, dst, n); // warn
480 }
481
482security.insecureAPI.bzero (C)
483""""""""""""""""""""""""""""""
484Warn on uses of the 'bzero' function.
485
486.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000487
Kristof Umann1a170322019-02-05 00:39:33 +0000488 void test() {
489 bzero(ptr, n); // warn
490 }
491
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000492security.insecureAPI.getpw (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000493""""""""""""""""""""""""""""""
494Warn on uses of the 'getpw' function.
495
496.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000497
Kristof Umann1a170322019-02-05 00:39:33 +0000498 void test() {
499 char buff[1024];
500 getpw(2, buff); // warn
501 }
502
503security.insecureAPI.gets (C)
504"""""""""""""""""""""""""""""
505Warn on uses of the 'gets' function.
506
507.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000508
Kristof Umann1a170322019-02-05 00:39:33 +0000509 void test() {
510 char buff[1024];
511 gets(buff); // warn
512 }
513
514security.insecureAPI.mkstemp (C)
515""""""""""""""""""""""""""""""""
516Warn when 'mkstemp' is passed fewer than 6 X's in the format string.
517
518.. code-block:: c
519
520 void test() {
521 mkstemp("XX"); // warn
522 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000523
524security.insecureAPI.mktemp (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000525"""""""""""""""""""""""""""""""
526Warn on uses of the ``mktemp`` function.
527
528.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000529
Kristof Umann1a170322019-02-05 00:39:33 +0000530 void test() {
531 char *x = mktemp("/tmp/zxcv"); // warn: insecure, use mkstemp
532 }
533
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000534security.insecureAPI.rand (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000535"""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000536Warn on uses of inferior random number generating functions (only if arc4random function is available):
Kristof Umann1a170322019-02-05 00:39:33 +0000537``drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, random, rand_r``.
538
539.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000540
Kristof Umann1a170322019-02-05 00:39:33 +0000541 void test() {
542 random(); // warn
543 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000544
Kristof Umann1a170322019-02-05 00:39:33 +0000545security.insecureAPI.strcpy (C)
546"""""""""""""""""""""""""""""""
547Warn on uses of the ``strcpy`` and ``strcat`` functions.
548
549.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000550
Kristof Umann1a170322019-02-05 00:39:33 +0000551 void test() {
552 char x[4];
553 char *y = "abcd";
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000554
Kristof Umann1a170322019-02-05 00:39:33 +0000555 strcpy(x, y); // warn
556 }
557
558
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000559security.insecureAPI.vfork (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000560""""""""""""""""""""""""""""""
561 Warn on uses of the 'vfork' function.
562
563.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000564
Kristof Umann1a170322019-02-05 00:39:33 +0000565 void test() {
566 vfork(); // warn
567 }
568
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000569security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C)
570"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Kristof Umann8d239992019-02-11 13:46:43 +0000571 Warn on occurrences of unsafe or deprecated buffer handling functions, which now have a secure variant: ``sprintf, vsprintf, scanf, wscanf, fscanf, fwscanf, vscanf, vwscanf, vfscanf, vfwscanf, sscanf, swscanf, vsscanf, vswscanf, swprintf, snprintf, vswprintf, vsnprintf, memcpy, memmove, strncpy, strncat, memset``
572
573.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000574
Kristof Umann8d239992019-02-11 13:46:43 +0000575 void test() {
576 char buf [5];
577 strncpy(buf, "a", 1); // warn
578 }
579
Kristof Umann1a170322019-02-05 00:39:33 +0000580.. _unix-checkers:
581
582unix
583^^^^
584POSIX/Unix checkers.
585
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000586unix.API (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000587""""""""""""
588Check calls to various UNIX/Posix functions: ``open, pthread_once, calloc, malloc, realloc, alloca``.
589
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000590.. literalinclude:: checkers/unix_api_example.c
Kristof Umann1a170322019-02-05 00:39:33 +0000591 :language: c
592
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000593unix.Malloc (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000594"""""""""""""""
595Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().
596
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000597.. literalinclude:: checkers/unix_malloc_example.c
Kristof Umann1a170322019-02-05 00:39:33 +0000598 :language: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000599
600unix.MallocSizeof (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000601"""""""""""""""""""""
602Check for dubious ``malloc`` arguments involving ``sizeof``.
603
604.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000605
Kristof Umann1a170322019-02-05 00:39:33 +0000606 void test() {
607 long *p = malloc(sizeof(short));
608 // warn: result is converted to 'long *', which is
609 // incompatible with operand type 'short'
610 free(p);
611 }
612
613unix.MismatchedDeallocator (C, C++)
614"""""""""""""""""""""""""""""""""""
615Check for mismatched deallocators.
616
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000617.. literalinclude:: checkers/mismatched_deallocator_example.cpp
Kristof Umann1a170322019-02-05 00:39:33 +0000618 :language: c
619
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000620unix.Vfork (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000621""""""""""""""
622Check for proper usage of ``vfork``.
623
624.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000625
Kristof Umann1a170322019-02-05 00:39:33 +0000626 int test(int x) {
627 pid_t pid = vfork(); // warn
628 if (pid != 0)
629 return 0;
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000630
Kristof Umann1a170322019-02-05 00:39:33 +0000631 switch (x) {
632 case 0:
633 pid = 1;
634 execl("", "", 0);
635 _exit(1);
636 break;
637 case 1:
638 x = 0; // warn: this assignment is prohibited
639 break;
640 case 2:
641 foo(); // warn: this function call is prohibited
642 break;
643 default:
644 return 0; // warn: return is prohibited
645 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000646
Kristof Umann1a170322019-02-05 00:39:33 +0000647 while(1);
648 }
649
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000650unix.cstring.BadSizeArg (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000651"""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000652Check the size argument passed into C string functions for common erroneous patterns. Use ``-Wno-strncat-size`` compiler option to mute other ``strncat``-related compiler warnings.
Kristof Umann1a170322019-02-05 00:39:33 +0000653
654.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000655
Kristof Umann1a170322019-02-05 00:39:33 +0000656 void test() {
657 char dest[3];
658 strncat(dest, """""""""""""""""""""""""*", sizeof(dest));
659 // warn: potential buffer overflow
660 }
661
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000662unix.cstrisng.NullArg (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000663"""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000664Check for null pointers being passed as arguments to C string functions:
Kristof Umann1a170322019-02-05 00:39:33 +0000665``strlen, strnlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp``.
666
667.. code-block:: c
668
669 int test() {
670 return strlen(0); // warn
671 }
672
673.. _osx-checkers:
674
675osx
676^^^
677OS X checkers.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000678
679osx.API (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000680"""""""""""
681Check for proper uses of various Apple APIs.
682
683.. code-block:: objc
684
685 void test() {
686 dispatch_once_t pred = 0;
687 dispatch_once(&pred, ^(){}); // warn: dispatch_once uses local
688 }
689
690osx.NumberObjectConversion (C, C++, ObjC)
691"""""""""""""""""""""""""""""""""""""""""
692Check for erroneous conversions of objects representing numbers into numbers.
693
694.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000695
Kristof Umann1a170322019-02-05 00:39:33 +0000696 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"];
697 // Warning: Comparing a pointer value of type 'NSNumber *'
698 // to a scalar integer value
699 if (photoCount > 0) {
700 [self displayPhotos];
701 }
702
703osx.ObjCProperty (ObjC)
704"""""""""""""""""""""""
705Check for proper uses of Objective-C properties.
706
707.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000708
Kristof Umann1a170322019-02-05 00:39:33 +0000709 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"];
710 // Warning: Comparing a pointer value of type 'NSNumber *'
711 // to a scalar integer value
712 if (photoCount > 0) {
713 [self displayPhotos];
714 }
715
716
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000717osx.SecKeychainAPI (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000718""""""""""""""""""""""
719Check for proper uses of Secure Keychain APIs.
720
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000721.. literalinclude:: checkers/seckeychainapi_example.m
Kristof Umann1a170322019-02-05 00:39:33 +0000722 :language: objc
723
724osx.cocoa.AtSync (ObjC)
725"""""""""""""""""""""""
726Check for nil pointers used as mutexes for @synchronized.
727
728.. code-block:: objc
729
730 void test(id x) {
731 if (!x)
732 @synchronized(x) {} // warn: nil value used as mutex
733 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000734
Kristof Umann1a170322019-02-05 00:39:33 +0000735 void test() {
736 id y;
737 @synchronized(y) {} // warn: uninitialized value used as mutex
738 }
739
740osx.cocoa.AutoreleaseWrite
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000741""""""""""""""""""""""""""
Kristof Umann1a170322019-02-05 00:39:33 +0000742Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C.
743
744osx.cocoa.ClassRelease (ObjC)
745"""""""""""""""""""""""""""""
746Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
747
748.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000749
Kristof Umann1a170322019-02-05 00:39:33 +0000750 @interface MyClass : NSObject
751 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000752
Kristof Umann1a170322019-02-05 00:39:33 +0000753 void test(void) {
754 [MyClass release]; // warn
755 }
756
757osx.cocoa.Dealloc (ObjC)
758""""""""""""""""""""""""
759Warn about Objective-C classes that lack a correct implementation of -dealloc
760
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000761.. literalinclude:: checkers/dealloc_example.m
Kristof Umann1a170322019-02-05 00:39:33 +0000762 :language: objc
763
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000764osx.cocoa.IncompatibleMethodTypes (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000765""""""""""""""""""""""""""""""""""""""""
766Warn about Objective-C method signatures with type incompatibilities.
767
768.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000769
Kristof Umann1a170322019-02-05 00:39:33 +0000770 @interface MyClass1 : NSObject
771 - (int)foo;
772 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000773
Kristof Umann1a170322019-02-05 00:39:33 +0000774 @implementation MyClass1
775 - (int)foo { return 1; }
776 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000777
Kristof Umann1a170322019-02-05 00:39:33 +0000778 @interface MyClass2 : MyClass1
779 - (float)foo;
780 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000781
Kristof Umann1a170322019-02-05 00:39:33 +0000782 @implementation MyClass2
783 - (float)foo { return 1.0; } // warn
784 @end
785
786osx.cocoa.Loops
787"""""""""""""""
788Improved modeling of loops using Cocoa collection types.
789
790osx.cocoa.MissingSuperCall (ObjC)
791"""""""""""""""""""""""""""""""""
792Warn about Objective-C methods that lack a necessary call to super.
793
794.. code-block:: objc
795
796 @interface Test : UIViewController
797 @end
798 @implementation test
799 - (void)viewDidLoad {} // warn
800 @end
801
802
803osx.cocoa.NSAutoreleasePool (ObjC)
804""""""""""""""""""""""""""""""""""
805Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode.
806
807.. code-block:: objc
808
809 void test() {
810 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
811 [pool release]; // warn
812 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000813
814osx.cocoa.NSError (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000815""""""""""""""""""""""""
816Check usage of NSError parameters.
817
818.. code-block:: objc
819
820 @interface A : NSObject
821 - (void)foo:(NSError """""""""""""""""""""""")error;
822 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000823
Kristof Umann1a170322019-02-05 00:39:33 +0000824 @implementation A
825 - (void)foo:(NSError """""""""""""""""""""""")error {
826 // warn: method accepting NSError"""""""""""""""""""""""" should have a non-void
827 // return value
828 }
829 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000830
Kristof Umann1a170322019-02-05 00:39:33 +0000831 @interface A : NSObject
832 - (BOOL)foo:(NSError """""""""""""""""""""""")error;
833 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000834
Kristof Umann1a170322019-02-05 00:39:33 +0000835 @implementation A
836 - (BOOL)foo:(NSError """""""""""""""""""""""")error {
837 *error = 0; // warn: potential null dereference
838 return 0;
839 }
840 @end
841
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000842osx.cocoa.NilArg (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000843"""""""""""""""""""""""
844Check for prohibited nil arguments to ObjC method calls.
845
846 - caseInsensitiveCompare:
847 - compare:
848 - compare:options:
849 - compare:options:range:
850 - compare:options:range:locale:
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000851 - componentsSeparatedByCharactersInSet:
Kristof Umann1a170322019-02-05 00:39:33 +0000852 - initWithFormat:
853
854.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000855
Kristof Umann1a170322019-02-05 00:39:33 +0000856 NSComparisonResult test(NSString *s) {
857 NSString *aString = nil;
858 return [s caseInsensitiveCompare:aString];
859 // warn: argument to 'NSString' method
860 // 'caseInsensitiveCompare:' cannot be nil
861 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000862
Kristof Umann1a170322019-02-05 00:39:33 +0000863
864osx.cocoa.NonNilReturnValue
865"""""""""""""""""""""""""""
866Models the APIs that are guaranteed to return a non-nil value.
867
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000868osx.cocoa.ObjCGenerics (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000869"""""""""""""""""""""""""""""
870Check for type errors when using Objective-C generics.
871
872.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000873
Kristof Umann1a170322019-02-05 00:39:33 +0000874 NSMutableArray *names = [NSMutableArray array];
875 NSMutableArray *birthDates = names;
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000876
Kristof Umann1a170322019-02-05 00:39:33 +0000877 // Warning: Conversion from value of type 'NSDate *'
878 // to incompatible type 'NSString *'
879 [birthDates addObject: [NSDate date]];
880
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000881osx.cocoa.RetainCount (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000882""""""""""""""""""""""""""""
883Check for leaks and improper reference count management
884
885.. code-block:: objc
886
887 void test() {
888 NSString *s = [[NSString alloc] init]; // warn
889 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000890
Kristof Umann1a170322019-02-05 00:39:33 +0000891 CFStringRef test(char *bytes) {
892 return CFStringCreateWithCStringNoCopy(
893 0, bytes, NSNEXTSTEPStringEncoding, 0); // warn
894 }
895
896
897osx.cocoa.RunLoopAutoreleaseLeak
898""""""""""""""""""""""""""""""""
899Check for leaked memory in autorelease pools that will never be drained.
900
901osx.cocoa.SelfInit (ObjC)
902"""""""""""""""""""""""""
903Check that 'self' is properly initialized inside an initializer method.
904
905.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000906
Kristof Umann1a170322019-02-05 00:39:33 +0000907 @interface MyObj : NSObject {
908 id x;
909 }
910 - (id)init;
911 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000912
Kristof Umann1a170322019-02-05 00:39:33 +0000913 @implementation MyObj
914 - (id)init {
915 [super init];
916 x = 0; // warn: instance variable used while 'self' is not
917 // initialized
918 return 0;
919 }
920 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000921
Kristof Umann1a170322019-02-05 00:39:33 +0000922 @interface MyObj : NSObject
923 - (id)init;
924 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000925
Kristof Umann1a170322019-02-05 00:39:33 +0000926 @implementation MyObj
927 - (id)init {
928 [super init];
929 return self; // warn: returning uninitialized 'self'
930 }
931 @end
932
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000933osx.cocoa.SuperDealloc (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000934"""""""""""""""""""""""""""""
935Warn about improper use of '[super dealloc]' in Objective-C.
936
937.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000938
Kristof Umann1a170322019-02-05 00:39:33 +0000939 @interface SuperDeallocThenReleaseIvarClass : NSObject {
940 NSObject *_ivar;
941 }
942 @end
943
944 @implementation SuperDeallocThenReleaseIvarClass
945 - (void)dealloc {
946 [super dealloc];
947 [_ivar release]; // warn
948 }
949 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000950
Kristof Umann1a170322019-02-05 00:39:33 +0000951osx.cocoa.UnusedIvars (ObjC)
952""""""""""""""""""""""""""""
953Warn about private ivars that are never used.
954
955.. code-block:: objc
956
957 @interface MyObj : NSObject {
958 @private
959 id x; // warn
960 }
961 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000962
Kristof Umann1a170322019-02-05 00:39:33 +0000963 @implementation MyObj
964 @end
965
966osx.cocoa.VariadicMethodTypes (ObjC)
967""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000968Check for passing non-Objective-C types to variadic collection
Kristof Umann1a170322019-02-05 00:39:33 +0000969initialization methods that expect only Objective-C types.
970
971.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000972
Kristof Umann1a170322019-02-05 00:39:33 +0000973 void test() {
974 [NSSet setWithObjects:@"Foo", "Bar", nil];
975 // warn: argument should be an ObjC pointer type, not 'char *'
976 }
977
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000978osx.coreFoundation.CFError (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000979""""""""""""""""""""""""""""""
980Check usage of CFErrorRef* parameters
981
982.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000983
Kristof Umann1a170322019-02-05 00:39:33 +0000984 void test(CFErrorRef *error) {
985 // warn: function accepting CFErrorRef* should have a
986 // non-void return
987 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000988
Kristof Umann1a170322019-02-05 00:39:33 +0000989 int foo(CFErrorRef *error) {
990 *error = 0; // warn: potential null dereference
991 return 0;
992 }
993
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000994osx.coreFoundation.CFNumber (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000995"""""""""""""""""""""""""""""""
996Check for proper uses of CFNumber APIs.
997
998.. code-block:: c
999
1000 CFNumberRef test(unsigned char x) {
1001 return CFNumberCreate(0, kCFNumberSInt16Type, &x);
1002 // warn: 8 bit integer is used to initialize a 16 bit integer
1003 }
1004
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001005osx.coreFoundation.CFRetainRelease (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001006""""""""""""""""""""""""""""""""""""""
1007Check for null arguments to CFRetain/CFRelease/CFMakeCollectable.
1008
1009.. code-block:: c
1010
1011 void test(CFTypeRef p) {
1012 if (!p)
1013 CFRetain(p); // warn
1014 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001015
Kristof Umann1a170322019-02-05 00:39:33 +00001016 void test(int x, CFTypeRef p) {
1017 if (p)
1018 return;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001019
Kristof Umann1a170322019-02-05 00:39:33 +00001020 CFRelease(p); // warn
1021 }
1022
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001023osx.coreFoundation.containers.OutOfBounds (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001024"""""""""""""""""""""""""""""""""""""""""""""
1025Checks for index out-of-bounds when using 'CFArray' API.
1026
1027.. code-block:: c
1028
1029 void test() {
1030 CFArrayRef A = CFArrayCreate(0, 0, 0, &kCFTypeArrayCallBacks);
1031 CFArrayGetValueAtIndex(A, 0); // warn
1032 }
1033
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001034osx.coreFoundation.containers.PointerSizedValues (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001035""""""""""""""""""""""""""""""""""""""""""""""""""""
1036Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values.
1037
1038.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001039
Kristof Umann1a170322019-02-05 00:39:33 +00001040 void test() {
1041 int x[] = { 1 };
1042 CFArrayRef A = CFArrayCreate(0, (const void """""""""""""""""""""""")x, 1,
1043 &kCFTypeArrayCallBacks); // warn
1044 }
1045
1046
1047.. _alpha-checkers:
1048
1049Experimental Checkers
1050---------------------
1051
1052*These are checkers with known issues or limitations that keep them from being on by default. They are likely to have false positives. Bug reports and especially patches are welcome.*
1053
1054alpha.clone
1055^^^^^^^^^^^
1056
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001057alpha.clone.CloneChecker (C, C++, ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001058"""""""""""""""""""""""""""""""""""""""
1059Reports similar pieces of code.
1060
1061.. code-block:: c
1062
1063 void log();
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001064
Kristof Umann1a170322019-02-05 00:39:33 +00001065 int max(int a, int b) { // warn
1066 log();
1067 if (a > b)
1068 return a;
1069 return b;
1070 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001071
Kristof Umann1a170322019-02-05 00:39:33 +00001072 int maxClone(int x, int y) { // similar code here
1073 log();
1074 if (x > y)
1075 return x;
1076 return y;
1077 }
1078
1079alpha.core.BoolAssignment (ObjC)
1080""""""""""""""""""""""""""""""""
1081Warn about assigning non-{0,1} values to boolean variables.
1082
1083.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001084
Kristof Umann1a170322019-02-05 00:39:33 +00001085 void test() {
1086 BOOL b = -1; // warn
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001087 }
Kristof Umann1a170322019-02-05 00:39:33 +00001088
1089alpha.core
1090^^^^^^^^^^
1091
1092alpha.core.CallAndMessageUnInitRefArg (C,C++, ObjC)
1093"""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001094Check for logical errors for function calls and Objective-C
Kristof Umann1a170322019-02-05 00:39:33 +00001095message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables).
1096
1097.. code-block:: c
1098
1099 void test(void) {
1100 int t;
1101 int &p = t;
1102 int &s = p;
1103 int &q = s;
1104 foo(q); // warn
1105 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001106
Kristof Umann1a170322019-02-05 00:39:33 +00001107 void test(void) {
1108 int x;
1109 foo(&x); // warn
1110 }
1111
1112alpha.core.CastSize (C)
1113"""""""""""""""""""""""
1114Check when casting a malloc'ed type ``T``, whether the size is a multiple of the size of ``T``.
1115
1116.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001117
Kristof Umann1a170322019-02-05 00:39:33 +00001118 void test() {
1119 int *x = (int *) malloc(11); // warn
1120 }
1121
1122alpha.core.CastToStruct (C, C++)
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001123""""""""""""""""""""""""""""""""
Kristof Umann1a170322019-02-05 00:39:33 +00001124Check for cast from non-struct pointer to struct pointer.
1125
1126.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001127
Kristof Umann1a170322019-02-05 00:39:33 +00001128 // C
1129 struct s {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001130
Kristof Umann1a170322019-02-05 00:39:33 +00001131 void test(int *p) {
1132 struct s *ps = (struct s *) p; // warn
1133 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001134
Kristof Umann1a170322019-02-05 00:39:33 +00001135 // C++
1136 class c {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001137
Kristof Umann1a170322019-02-05 00:39:33 +00001138 void test(int *p) {
1139 c *pc = (c *) p; // warn
1140 }
1141
1142alpha.core.Conversion (C, C++, ObjC)
1143""""""""""""""""""""""""""""""""""""
1144Loss of sign/precision in implicit conversions.
1145
1146.. code-block:: c
1147
1148 void test(unsigned U, signed S) {
1149 if (S > 10) {
1150 if (U < S) {
1151 }
1152 }
1153 if (S < -10) {
1154 if (U < S) { // warn (loss of sign)
1155 }
1156 }
1157 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001158
Kristof Umann1a170322019-02-05 00:39:33 +00001159 void test() {
1160 long long A = 1LL << 60;
1161 short X = A; // warn (loss of precision)
1162 }
1163
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001164alpha.core.DynamicTypeChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001165""""""""""""""""""""""""""""""""""""
1166Check for cases where the dynamic and the static type of an object are unrelated.
1167
1168
1169.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001170
Kristof Umann1a170322019-02-05 00:39:33 +00001171 id date = [NSDate date];
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001172
Kristof Umann1a170322019-02-05 00:39:33 +00001173 // Warning: Object has a dynamic type 'NSDate *' which is
1174 // incompatible with static type 'NSNumber *'"
1175 NSNumber *number = date;
1176 [number doubleValue];
1177
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001178alpha.core.FixedAddr (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001179""""""""""""""""""""""""
1180Check for assignment of a fixed address to a pointer.
1181
1182.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001183
Kristof Umann1a170322019-02-05 00:39:33 +00001184 void test() {
1185 int *p;
1186 p = (int *) 0x10000; // warn
1187 }
1188
1189alpha.core.IdenticalExpr (C, C++)
1190"""""""""""""""""""""""""""""""""
1191Warn about unintended use of identical expressions in operators.
1192
1193.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001194
Kristof Umann1a170322019-02-05 00:39:33 +00001195 // C
1196 void test() {
1197 int a = 5;
1198 int b = a | 4 | a; // warn: identical expr on both sides
1199 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001200
Kristof Umann1a170322019-02-05 00:39:33 +00001201 // C++
1202 bool f(void);
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001203
Kristof Umann1a170322019-02-05 00:39:33 +00001204 void test(bool b) {
1205 int i = 10;
1206 if (f()) { // warn: true and false branches are identical
1207 do {
1208 i--;
1209 } while (f());
1210 } else {
1211 do {
1212 i--;
1213 } while (f());
1214 }
1215 }
1216
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001217alpha.core.PointerArithm (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001218""""""""""""""""""""""""""""
1219Check for pointer arithmetic on locations other than array elements.
1220
1221.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001222
Kristof Umann1a170322019-02-05 00:39:33 +00001223 void test() {
1224 int x;
1225 int *p;
1226 p = &x + 1; // warn
1227 }
1228
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001229alpha.core.PointerSub (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001230"""""""""""""""""""""""""
1231Check for pointer subtractions on two pointers pointing to different memory chunks.
1232
1233.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001234
Kristof Umann1a170322019-02-05 00:39:33 +00001235 void test() {
1236 int x, y;
1237 int d = &y - &x; // warn
1238 }
1239
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001240alpha.core.SizeofPtr (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001241""""""""""""""""""""""""
1242Warn about unintended use of ``sizeof()`` on pointer expressions.
1243
1244.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001245
Kristof Umann1a170322019-02-05 00:39:33 +00001246 struct s {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001247
Kristof Umann1a170322019-02-05 00:39:33 +00001248 int test(struct s *p) {
1249 return sizeof(p);
1250 // warn: sizeof(ptr) can produce an unexpected result
1251 }
1252
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001253alpha.core.StackAddressAsyncEscape (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001254""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001255Check that addresses to stack memory do not escape the function that involves dispatch_after or dispatch_async.
Kristof Umann1a170322019-02-05 00:39:33 +00001256This checker is a part of ``core.StackAddressEscape``, but is temporarily disabled until some false positives are fixed.
1257
1258.. code-block:: c
1259
1260 dispatch_block_t test_block_inside_block_async_leak() {
1261 int x = 123;
1262 void (^inner)(void) = ^void(void) {
1263 int y = x;
1264 ++y;
1265 };
1266 void (^outer)(void) = ^void(void) {
1267 int z = x;
1268 ++z;
1269 inner();
1270 };
1271 return outer; // warn: address of stack-allocated block is captured by a
1272 // returned block
1273 }
1274
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001275alpha.core.TestAfterDivZero (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001276"""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001277Check for division by variable that is later compared against 0.
Kristof Umann1a170322019-02-05 00:39:33 +00001278Either the comparison is useless or there is division by zero.
1279
1280.. code-block:: c
1281
1282 void test(int x) {
1283 var = 77 / x;
1284 if (x == 0) { } // warn
1285 }
1286
1287alpha.cplusplus
1288^^^^^^^^^^^^^^^
1289
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001290alpha.cplusplus.DeleteWithNonVirtualDtor (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001291""""""""""""""""""""""""""""""""""""""""""""""
1292Reports destructions of polymorphic objects with a non-virtual destructor in their base class.
1293
1294.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001295
Kristof Umann1a170322019-02-05 00:39:33 +00001296 NonVirtual *create() {
1297 NonVirtual *x = new NVDerived(); // note: conversion from derived to base
1298 // happened here
1299 return x;
1300 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001301
Kristof Umann1a170322019-02-05 00:39:33 +00001302 void sink(NonVirtual *x) {
1303 delete x; // warn: destruction of a polymorphic object with no virtual
1304 // destructor
1305 }
1306
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001307alpha.cplusplus.EnumCastOutOfRange (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001308""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001309Check for integer to enumeration casts that could result in undefined values.
Kristof Umann1a170322019-02-05 00:39:33 +00001310
1311.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001312
Kristof Umann1a170322019-02-05 00:39:33 +00001313 enum TestEnum {
1314 A = 0
1315 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001316
Kristof Umann1a170322019-02-05 00:39:33 +00001317 void foo() {
1318 TestEnum t = static_cast(-1);
1319 // warn: the value provided to the cast expression is not in
1320 the valid range of values for the enum
1321
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001322alpha.cplusplus.InvalidatedIterator (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001323"""""""""""""""""""""""""""""""""""""""""
1324Check for use of invalidated iterators.
1325
1326.. code-block:: cpp
1327
1328 void bad_copy_assign_operator_list1(std::list &L1,
1329 const std::list &L2) {
1330 auto i0 = L1.cbegin();
1331 L1 = L2;
1332 *i0; // warn: invalidated iterator accessed
1333 }
1334
1335
1336alpha.cplusplus.IteratorRange (C++)
1337"""""""""""""""""""""""""""""""""""
1338Check for iterators used outside their valid ranges.
1339
1340.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001341
Kristof Umann1a170322019-02-05 00:39:33 +00001342 void simple_bad_end(const std::vector &v) {
1343 auto i = v.end();
1344 *i; // warn: iterator accessed outside of its range
1345 }
1346
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001347alpha.cplusplus.MismatchedIterator (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001348""""""""""""""""""""""""""""""""""""""""
1349Check for use of iterators of different containers where iterators of the same container are expected.
1350
1351.. code-block:: cpp
1352
1353 void bad_insert3(std::vector &v1, std::vector &v2) {
1354 v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed
1355 // using foreign
1356 // iterator argument
1357 v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of
1358 // different containers
1359 // used where the same
1360 // container is
1361 // expected
1362 v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of
1363 // different containers
1364 // used where the same
1365 // container is
1366 // expected
1367 }
1368
1369alpha.cplusplus.MisusedMovedObject (C++)
1370""""""""""""""""""""""""""""""""""""""""
1371Method calls on a moved-from object and copying a moved-from object will be reported.
1372
1373
1374.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001375
Kristof Umann1a170322019-02-05 00:39:33 +00001376 struct A {
1377 void foo() {}
1378 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001379
Kristof Umann1a170322019-02-05 00:39:33 +00001380 void f() {
1381 A a;
1382 A b = std::move(a); // note: 'a' became 'moved-from' here
1383 a.foo(); // warn: method call on a 'moved-from' object 'a'
1384 }
1385
1386alpha.cplusplus.UninitializedObject (C++)
1387"""""""""""""""""""""""""""""""""""""""""
1388
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001389This checker reports uninitialized fields in objects created after a constructor call.
1390It doesn't only find direct uninitialized fields, but rather makes a deep inspection
Kristof Umann1a170322019-02-05 00:39:33 +00001391of the object, analyzing all of it's fields subfields.
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001392The checker regards inherited fields as direct fields, so one will
Kristof Umann1a170322019-02-05 00:39:33 +00001393recieve warnings for uninitialized inherited data members as well.
1394
1395.. code-block:: cpp
1396
1397 // With Pedantic and CheckPointeeInitialization set to true
1398
1399 struct A {
1400 struct B {
1401 int x; // note: uninitialized field 'this->b.x'
1402 // note: uninitialized field 'this->bptr->x'
1403 int y; // note: uninitialized field 'this->b.y'
1404 // note: uninitialized field 'this->bptr->y'
1405 };
1406 int *iptr; // note: uninitialized pointer 'this->iptr'
1407 B b;
1408 B *bptr;
1409 char *cptr; // note: uninitialized pointee 'this->cptr'
1410
1411 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
1412 };
1413
1414 void f() {
1415 A::B b;
1416 char c;
1417 A a(&b, &c); // warning: 6 uninitialized fields
1418 // after the constructor call
1419 }
1420
1421 // With Pedantic set to false and
1422 // CheckPointeeInitialization set to true
1423 // (every field is uninitialized)
1424
1425 struct A {
1426 struct B {
1427 int x;
1428 int y;
1429 };
1430 int *iptr;
1431 B b;
1432 B *bptr;
1433 char *cptr;
1434
1435 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
1436 };
1437
1438 void f() {
1439 A::B b;
1440 char c;
1441 A a(&b, &c); // no warning
1442 }
1443
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001444 // With Pedantic set to true and
Kristof Umann1a170322019-02-05 00:39:33 +00001445 // CheckPointeeInitialization set to false
1446 // (pointees are regarded as initialized)
1447
1448 struct A {
1449 struct B {
1450 int x; // note: uninitialized field 'this->b.x'
1451 int y; // note: uninitialized field 'this->b.y'
1452 };
1453 int *iptr; // note: uninitialized pointer 'this->iptr'
1454 B b;
1455 B *bptr;
1456 char *cptr;
1457
1458 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
1459 };
1460
1461 void f() {
1462 A::B b;
1463 char c;
1464 A a(&b, &c); // warning: 3 uninitialized fields
1465 // after the constructor call
1466 }
1467
1468
1469**Options**
1470
1471This checker has several options which can be set from command line (e.g. ``-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true``):
1472
1473* ``Pedantic`` (boolean). If to false, the checker won't emit warnings for objects that don't have at least one initialized field. Defaults to false.
1474
1475* ``NotesAsWarnings`` (boolean). If set to true, the checker will emit a warning for each uninitalized field, as opposed to emitting one warning per constructor call, and listing the uninitialized fields that belongs to it in notes. *Defaults to false.*.
1476
1477* ``CheckPointeeInitialization`` (boolean). If set to false, the checker will not analyze the pointee of pointer/reference fields, and will only check whether the object itself is initialized. *Defaults to false.*.
1478
1479* ``IgnoreRecordsWithField`` (string). If supplied, the checker will not analyze structures that have a field with a name or type name that matches the given pattern. *Defaults to ""*. Can be set with ``-analyzer-config alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"``.
1480
1481
1482alpha.deadcode
1483^^^^^^^^^^^^^^
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001484alpha.deadcode.UnreachableCode (C, C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001485"""""""""""""""""""""""""""""""""""""""
1486Check unreachable code.
1487
1488.. code-block:: cpp
1489
1490 // C
1491 int test() {
1492 int x = 1;
1493 while(x);
1494 return x; // warn
1495 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001496
Kristof Umann1a170322019-02-05 00:39:33 +00001497 // C++
1498 void test() {
1499 int a = 2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001500
Kristof Umann1a170322019-02-05 00:39:33 +00001501 while (a > 1)
1502 a--;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001503
Kristof Umann1a170322019-02-05 00:39:33 +00001504 if (a > 1)
1505 a++; // warn
1506 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001507
Kristof Umann1a170322019-02-05 00:39:33 +00001508 // Objective-C
1509 void test(id x) {
1510 return;
1511 [x retain]; // warn
1512 }
1513
1514alpha.llvm
1515^^^^^^^^^^
1516
1517alpha.llvm.Conventions
1518""""""""""""""""""""""
1519
1520Check code for LLVM codebase conventions:
1521
1522* A StringRef should not be bound to a temporary std::string whose lifetime is shorter than the StringRef's.
1523* Clang AST nodes should not have fields that can allocate memory.
1524
1525
1526alpha.osx
1527^^^^^^^^^
1528
1529alpha.osx.cocoa.DirectIvarAssignment (ObjC)
1530"""""""""""""""""""""""""""""""""""""""""""
1531Check for direct assignments to instance variables.
1532
1533
1534.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001535
Kristof Umann1a170322019-02-05 00:39:33 +00001536 @interface MyClass : NSObject {}
1537 @property (readonly) id A;
1538 - (void) foo;
1539 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001540
Kristof Umann1a170322019-02-05 00:39:33 +00001541 @implementation MyClass
1542 - (void) foo {
1543 _A = 0; // warn
1544 }
1545 @end
1546
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001547alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001548""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001549Check for direct assignments to instance variables in
Kristof Umann1a170322019-02-05 00:39:33 +00001550the methods annotated with ``objc_no_direct_instance_variable_assignment``.
1551
1552.. code-block:: objc
1553
1554 @interface MyClass : NSObject {}
1555 @property (readonly) id A;
1556 - (void) fAnnotated __attribute__((
1557 annotate("objc_no_direct_instance_variable_assignment")));
1558 - (void) fNotAnnotated;
1559 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001560
Kristof Umann1a170322019-02-05 00:39:33 +00001561 @implementation MyClass
1562 - (void) fAnnotated {
1563 _A = 0; // warn
1564 }
1565 - (void) fNotAnnotated {
1566 _A = 0; // no warn
1567 }
1568 @end
1569
1570
1571alpha.osx.cocoa.InstanceVariableInvalidation (ObjC)
1572"""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001573Check that the invalidatable instance variables are
Kristof Umann1a170322019-02-05 00:39:33 +00001574invalidated in the methods annotated with objc_instance_variable_invalidator.
1575
1576.. code-block:: objc
1577
1578 @protocol Invalidation <NSObject>
1579 - (void) invalidate
1580 __attribute__((annotate("objc_instance_variable_invalidator")));
1581 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001582
Kristof Umann1a170322019-02-05 00:39:33 +00001583 @interface InvalidationImpObj : NSObject <Invalidation>
1584 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001585
Kristof Umann1a170322019-02-05 00:39:33 +00001586 @interface SubclassInvalidationImpObj : InvalidationImpObj {
1587 InvalidationImpObj *var;
1588 }
1589 - (void)invalidate;
1590 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001591
Kristof Umann1a170322019-02-05 00:39:33 +00001592 @implementation SubclassInvalidationImpObj
1593 - (void) invalidate {}
1594 @end
1595 // warn: var needs to be invalidated or set to nil
1596
1597alpha.osx.cocoa.MissingInvalidationMethod (ObjC)
1598""""""""""""""""""""""""""""""""""""""""""""""""
1599Check that the invalidation methods are present in classes that contain invalidatable instance variables.
1600
1601.. code-block:: objc
1602
1603 @protocol Invalidation <NSObject>
1604 - (void)invalidate
1605 __attribute__((annotate("objc_instance_variable_invalidator")));
1606 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001607
Kristof Umann1a170322019-02-05 00:39:33 +00001608 @interface NeedInvalidation : NSObject <Invalidation>
1609 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001610
Kristof Umann1a170322019-02-05 00:39:33 +00001611 @interface MissingInvalidationMethodDecl : NSObject {
1612 NeedInvalidation *Var; // warn
1613 }
1614 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001615
Kristof Umann1a170322019-02-05 00:39:33 +00001616 @implementation MissingInvalidationMethodDecl
1617 @end
1618
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001619alpha.osx.cocoa.localizability.PluralMisuseChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001620"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1621Warns against using one vs. many plural pattern in code when generating localized strings.
1622
1623.. code-block:: objc
1624
1625 NSString *reminderText =
1626 NSLocalizedString(@"None", @"Indicates no reminders");
1627 if (reminderCount == 1) {
1628 // Warning: Plural cases are not supported across all languages.
1629 // Use a .stringsdict file instead
1630 reminderText =
1631 NSLocalizedString(@"1 Reminder", @"Indicates single reminder");
1632 } else if (reminderCount >= 2) {
1633 // Warning: Plural cases are not supported across all languages.
1634 // Use a .stringsdict file instead
1635 reminderText =
1636 [NSString stringWithFormat:
1637 NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"),
1638 reminderCount];
1639 }
1640
1641alpha.security
1642^^^^^^^^^^^^^^
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001643alpha.security.ArrayBound (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001644"""""""""""""""""""""""""""""
1645Warn about buffer overflows (older checker).
1646
1647.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001648
Kristof Umann1a170322019-02-05 00:39:33 +00001649 void test() {
1650 char *s = "";
1651 char c = s[1]; // warn
1652 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001653
Kristof Umann1a170322019-02-05 00:39:33 +00001654 struct seven_words {
1655 int c[7];
1656 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001657
Kristof Umann1a170322019-02-05 00:39:33 +00001658 void test() {
1659 struct seven_words a, *p;
1660 p = &a;
1661 p[0] = a;
1662 p[1] = a;
1663 p[2] = a; // warn
1664 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001665
Kristof Umann1a170322019-02-05 00:39:33 +00001666 // note: requires unix.Malloc or
1667 // alpha.unix.MallocWithAnnotations checks enabled.
1668 void test() {
1669 int *p = malloc(12);
1670 p[3] = 4; // warn
1671 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001672
Kristof Umann1a170322019-02-05 00:39:33 +00001673 void test() {
1674 char a[2];
1675 int *b = (int*)a;
1676 b[1] = 3; // warn
1677 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001678
1679alpha.security.ArrayBoundV2 (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001680"""""""""""""""""""""""""""""""
1681Warn about buffer overflows (newer checker).
1682
1683.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001684
Kristof Umann1a170322019-02-05 00:39:33 +00001685 void test() {
1686 char *s = "";
1687 char c = s[1]; // warn
1688 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001689
Kristof Umann1a170322019-02-05 00:39:33 +00001690 void test() {
1691 int buf[100];
1692 int *p = buf;
1693 p = p + 99;
1694 p[1] = 1; // warn
1695 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001696
Kristof Umann1a170322019-02-05 00:39:33 +00001697 // note: compiler has internal check for this.
1698 // Use -Wno-array-bounds to suppress compiler warning.
1699 void test() {
1700 int buf[100][100];
1701 buf[0][-1] = 1; // warn
1702 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001703
Kristof Umann1a170322019-02-05 00:39:33 +00001704 // note: requires alpha.security.taint check turned on.
1705 void test() {
1706 char s[] = "abc";
1707 int x = getchar();
1708 char c = s[x]; // warn: index is tainted
1709 }
1710
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001711alpha.security.MallocOverflow (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001712"""""""""""""""""""""""""""""""""
1713Check for overflows in the arguments to malloc().
1714
1715.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001716
Kristof Umann1a170322019-02-05 00:39:33 +00001717 void test(int n) {
1718 void *p = malloc(n * sizeof(int)); // warn
1719 }
1720
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001721alpha.security.MmapWriteExec (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001722""""""""""""""""""""""""""""""""
1723Warn on mmap() calls that are both writable and executable.
1724
1725.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001726
Kristof Umann1a170322019-02-05 00:39:33 +00001727 void test(int n) {
1728 void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC,
1729 MAP_PRIVATE | MAP_ANON, -1, 0);
1730 // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to
1731 // exploitable memory regions, which could be overwritten with malicious
1732 // code
1733 }
1734
1735alpha.security.ReturnPtrRange (C)
1736"""""""""""""""""""""""""""""""""
1737Check for an out-of-bound pointer being returned to callers.
1738
1739.. code-block:: c
1740
1741 static int A[10];
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001742
Kristof Umann1a170322019-02-05 00:39:33 +00001743 int *test() {
1744 int *p = A + 10;
1745 return p; // warn
1746 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001747
Kristof Umann1a170322019-02-05 00:39:33 +00001748 int test(void) {
1749 int x;
1750 return x; // warn: undefined or garbage returned
1751 }
1752
1753alpha.security.taint.TaintPropagation (C, C++)
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001754""""""""""""""""""""""""""""""""""""""""""""""
1755Generate taint information used by other checkers.
Kristof Umann1a170322019-02-05 00:39:33 +00001756A data is tainted when it comes from an unreliable source.
1757
1758.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001759
Kristof Umann1a170322019-02-05 00:39:33 +00001760 void test() {
1761 char x = getchar(); // 'x' marked as tainted
1762 system(&x); // warn: untrusted data is passed to a system call
1763 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001764
Kristof Umann1a170322019-02-05 00:39:33 +00001765 // note: compiler internally checks if the second param to
1766 // sprintf is a string literal or not.
1767 // Use -Wno-format-security to suppress compiler warning.
1768 void test() {
1769 char s[10], buf[10];
1770 fscanf(stdin, "%s", s); // 's' marked as tainted
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001771
Kristof Umann1a170322019-02-05 00:39:33 +00001772 sprintf(buf, s); // warn: untrusted data as a format string
1773 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001774
Kristof Umann1a170322019-02-05 00:39:33 +00001775 void test() {
1776 size_t ts;
1777 scanf("%zd", &ts); // 'ts' marked as tainted
1778 int *p = (int *)malloc(ts * sizeof(int));
1779 // warn: untrusted data as buffer size
1780 }
1781
1782alpha.unix
1783^^^^^^^^^^^
1784
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001785alpha.unix.BlockInCriticalSection (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001786"""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001787Check for calls to blocking functions inside a critical section.
Kristof Umann1a170322019-02-05 00:39:33 +00001788Applies to: ``lock, unlock, sleep, getc, fgets, read, recv, pthread_mutex_lock,``
1789`` pthread_mutex_unlock, mtx_lock, mtx_timedlock, mtx_trylock, mtx_unlock, lock_guard, unique_lock``
1790
1791.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001792
Kristof Umann1a170322019-02-05 00:39:33 +00001793 void test() {
1794 std::mutex m;
1795 m.lock();
1796 sleep(3); // warn: a blocking function sleep is called inside a critical
1797 // section
1798 m.unlock();
1799 }
1800
1801alpha.unix.Chroot (C)
1802"""""""""""""""""""""
1803Check improper use of chroot.
1804
1805.. code-block:: c
1806
1807 void f();
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001808
Kristof Umann1a170322019-02-05 00:39:33 +00001809 void test() {
1810 chroot("/usr/local");
1811 f(); // warn: no call of chdir("/") immediately after chroot
1812 }
1813
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001814alpha.unix.PthreadLock (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001815""""""""""""""""""""""""""
1816Simple lock -> unlock checker.
1817Applies to: ``pthread_mutex_lock, pthread_rwlock_rdlock, pthread_rwlock_wrlock, lck_mtx_lock, lck_rw_lock_exclusive``
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001818``lck_rw_lock_shared, pthread_mutex_trylock, pthread_rwlock_tryrdlock, pthread_rwlock_tryrwlock, lck_mtx_try_lock,
Kristof Umann1a170322019-02-05 00:39:33 +00001819lck_rw_try_lock_exclusive, lck_rw_try_lock_shared, pthread_mutex_unlock, pthread_rwlock_unlock, lck_mtx_unlock, lck_rw_done``.
1820
1821
1822.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001823
Kristof Umann1a170322019-02-05 00:39:33 +00001824 pthread_mutex_t mtx;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001825
Kristof Umann1a170322019-02-05 00:39:33 +00001826 void test() {
1827 pthread_mutex_lock(&mtx);
1828 pthread_mutex_lock(&mtx);
1829 // warn: this lock has already been acquired
1830 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001831
Kristof Umann1a170322019-02-05 00:39:33 +00001832 lck_mtx_t lck1, lck2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001833
Kristof Umann1a170322019-02-05 00:39:33 +00001834 void test() {
1835 lck_mtx_lock(&lck1);
1836 lck_mtx_lock(&lck2);
1837 lck_mtx_unlock(&lck1);
1838 // warn: this was not the most recently acquired lock
1839 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001840
Kristof Umann1a170322019-02-05 00:39:33 +00001841 lck_mtx_t lck1, lck2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001842
Kristof Umann1a170322019-02-05 00:39:33 +00001843 void test() {
1844 if (lck_mtx_try_lock(&lck1) == 0)
1845 return;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001846
Kristof Umann1a170322019-02-05 00:39:33 +00001847 lck_mtx_lock(&lck2);
1848 lck_mtx_unlock(&lck1);
1849 // warn: this was not the most recently acquired lock
1850 }
1851
1852alpha.unix.SimpleStream (C)
1853"""""""""""""""""""""""""""
1854Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fclose``
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001855(demo checker, the subject of the demo (`Slides <http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf>`_ ,
1856`Video <https://youtu.be/kdxlsP5QVPw>`_) by Anna Zaks and Jordan Rose presented at the
Kristof Umann1a170322019-02-05 00:39:33 +00001857`2012 LLVM Developers' Meeting <http://llvm.org/devmtg/2012-11/>`_).
1858
1859.. code-block:: c
1860
1861 void test() {
1862 FILE *F = fopen("myfile.txt", "w");
1863 } // warn: opened file is never closed
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001864
Kristof Umann1a170322019-02-05 00:39:33 +00001865 void test() {
1866 FILE *F = fopen("myfile.txt", "w");
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001867
Kristof Umann1a170322019-02-05 00:39:33 +00001868 if (F)
1869 fclose(F);
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001870
Kristof Umann1a170322019-02-05 00:39:33 +00001871 fclose(F); // warn: closing a previously closed file stream
1872 }
1873
1874alpha.unix.Stream (C)
1875"""""""""""""""""""""
1876Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,``
1877``fsetpos, clearerr, feof, ferror, fileno``.
1878
1879.. code-block:: c
1880
1881 void test() {
1882 FILE *p = fopen("foo", "r");
1883 } // warn: opened file is never closed
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001884
Kristof Umann1a170322019-02-05 00:39:33 +00001885 void test() {
1886 FILE *p = fopen("foo", "r");
1887 fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
1888 fclose(p);
1889 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001890
Kristof Umann1a170322019-02-05 00:39:33 +00001891 void test() {
1892 FILE *p = fopen("foo", "r");
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001893
Kristof Umann1a170322019-02-05 00:39:33 +00001894 if (p)
1895 fseek(p, 1, 3);
1896 // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001897
Kristof Umann1a170322019-02-05 00:39:33 +00001898 fclose(p);
1899 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001900
Kristof Umann1a170322019-02-05 00:39:33 +00001901 void test() {
1902 FILE *p = fopen("foo", "r");
1903 fclose(p);
1904 fclose(p); // warn: already closed
1905 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001906
Kristof Umann1a170322019-02-05 00:39:33 +00001907 void test() {
1908 FILE *p = tmpfile();
1909 ftell(p); // warn: stream pointer might be NULL
1910 fclose(p);
1911 }
1912
1913
1914alpha.unix.cstring.BufferOverlap (C)
1915""""""""""""""""""""""""""""""""""""
1916Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy``.
1917
1918.. code-block:: c
1919
1920 void test() {
1921 int a[4] = {0};
1922 memcpy(a + 2, a + 1, 8); // warn
1923 }
1924
1925alpha.unix.cstring.NotNullTerminated (C)
1926""""""""""""""""""""""""""""""""""""""""
1927Check for arguments which are not null-terminated strings; applies to: ``strlen, strnlen, strcpy, strncpy, strcat, strncat``.
1928
1929.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001930
Kristof Umann1a170322019-02-05 00:39:33 +00001931 void test() {
1932 int y = strlen((char *)&test); // warn
1933 }
1934
1935alpha.unix.cstring.OutOfBounds (C)
1936""""""""""""""""""""""""""""""""""
1937Check for out-of-bounds access in string functions; applies to:`` strncopy, strncat``.
1938
1939
1940.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001941
Kristof Umann1a170322019-02-05 00:39:33 +00001942 void test() {
1943 int y = strlen((char *)&test); // warn
1944 }
1945
Mandeep Singh Grangc0773ab2019-03-08 20:13:53 +00001946alpha.nondeterminism.PointerSorting (C++)
1947"""""""""""""""""""""""""
1948Check for non-determinism caused by sorting of pointers.
1949
1950.. code-block:: c
1951
1952 void test() {
1953 int a = 1, b = 2;
1954 std::vector<int *> V = {&a, &b};
1955 std::sort(V.begin(), V.end()); // warn
1956 }
1957
Kristof Umann1a170322019-02-05 00:39:33 +00001958
1959Debug Checkers
1960---------------
1961
1962.. _debug-checkers:
1963
1964
1965debug
1966^^^^^
1967
1968Checkers used for debugging the analyzer.
Kristof Umanndccfaff2019-02-05 10:19:39 +00001969:doc:`developer-docs/DebugChecks` page contains a detailed description.
Kristof Umann1a170322019-02-05 00:39:33 +00001970
1971debug.AnalysisOrder
1972"""""""""""""""""""
1973Print callbacks that are called during analysis in order.
1974
1975debug.ConfigDumper
1976""""""""""""""""""
1977Dump config table.
1978
1979debug.DumpCFG Display
1980"""""""""""""""""""""
1981Control-Flow Graphs.
1982
1983debug.DumpCallGraph
1984"""""""""""""""""""
1985Display Call Graph.
1986
1987debug.DumpCalls
1988"""""""""""""""
1989Print calls as they are traversed by the engine.
1990
1991debug.DumpDominators
1992""""""""""""""""""""
1993Print the dominance tree for a given CFG.
1994
1995debug.DumpLiveVars
1996""""""""""""""""""
1997Print results of live variable analysis.
1998
1999debug.DumpTraversal
2000"""""""""""""""""""
2001Print branch conditions as they are traversed by the engine.
2002
2003debug.ExprInspection
2004""""""""""""""""""""
2005Check the analyzer's understanding of expressions.
2006
2007debug.Stats
2008"""""""""""
2009Emit warnings with analyzer statistics.
2010
2011debug.TaintTest
2012"""""""""""""""
2013Mark tainted symbols as such.
2014
2015debug.ViewCFG
2016"""""""""""""
2017View Control-Flow Graphs using GraphViz.
2018
2019debug.ViewCallGraph
2020"""""""""""""""""""
2021View Call Graph using GraphViz.
2022
2023debug.ViewExplodedGraph
2024"""""""""""""""""""""""
2025View Exploded Graphs using GraphViz.
2026