blob: 6a266eb1d9e9012526a8ca5235e95f0251f81c8d [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
Mandeep Singh Grang0cdc5dd2019-05-24 19:24:08 +0000214cplusplus
215^^^^^^^^^
Kristof Umann1a170322019-02-05 00:39:33 +0000216
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
Kristof Umann85e0ff72019-04-19 23:33:50 +0000342optin.cplusplus.UninitializedObject (C++)
Nico Weber83c95b12019-05-03 18:54:18 +0000343"""""""""""""""""""""""""""""""""""""""""
Kristof Umann85e0ff72019-04-19 23:33:50 +0000344
345This checker reports uninitialized fields in objects created after a constructor
346call. It doesn't only find direct uninitialized fields, but rather makes a deep
347inspection of the object, analyzing all of it's fields subfields.
348The checker regards inherited fields as direct fields, so one will recieve
349warnings for uninitialized inherited data members as well.
350
351.. code-block:: cpp
352
353 // With Pedantic and CheckPointeeInitialization set to true
354
355 struct A {
356 struct B {
357 int x; // note: uninitialized field 'this->b.x'
358 // note: uninitialized field 'this->bptr->x'
359 int y; // note: uninitialized field 'this->b.y'
360 // note: uninitialized field 'this->bptr->y'
361 };
362 int *iptr; // note: uninitialized pointer 'this->iptr'
363 B b;
364 B *bptr;
365 char *cptr; // note: uninitialized pointee 'this->cptr'
366
367 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
368 };
369
370 void f() {
371 A::B b;
372 char c;
373 A a(&b, &c); // warning: 6 uninitialized fields
374 // after the constructor call
375 }
376
377 // With Pedantic set to false and
378 // CheckPointeeInitialization set to true
379 // (every field is uninitialized)
380
381 struct A {
382 struct B {
383 int x;
384 int y;
385 };
386 int *iptr;
387 B b;
388 B *bptr;
389 char *cptr;
390
391 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
392 };
393
394 void f() {
395 A::B b;
396 char c;
397 A a(&b, &c); // no warning
398 }
399
400 // With Pedantic set to true and
401 // CheckPointeeInitialization set to false
402 // (pointees are regarded as initialized)
403
404 struct A {
405 struct B {
406 int x; // note: uninitialized field 'this->b.x'
407 int y; // note: uninitialized field 'this->b.y'
408 };
409 int *iptr; // note: uninitialized pointer 'this->iptr'
410 B b;
411 B *bptr;
412 char *cptr;
413
414 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {}
415 };
416
417 void f() {
418 A::B b;
419 char c;
420 A a(&b, &c); // warning: 3 uninitialized fields
421 // after the constructor call
422 }
423
424
425**Options**
426
427This checker has several options which can be set from command line (e.g.
428``-analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true``):
429
430* ``Pedantic`` (boolean). If to false, the checker won't emit warnings for
431 objects that don't have at least one initialized field. Defaults to false.
432
433* ``NotesAsWarnings`` (boolean). If set to true, the checker will emit a
434 warning for each uninitalized field, as opposed to emitting one warning per
435 constructor call, and listing the uninitialized fields that belongs to it in
436 notes. *Defaults to false*.
437
438* ``CheckPointeeInitialization`` (boolean). If set to false, the checker will
439 not analyze the pointee of pointer/reference fields, and will only check
440 whether the object itself is initialized. *Defaults to false*.
441
442* ``IgnoreRecordsWithField`` (string). If supplied, the checker will not analyze
443 structures that have a field with a name or type name that matches the given
444 pattern. *Defaults to ""*.
445
Kristof Umann1a170322019-02-05 00:39:33 +0000446optin.cplusplus.VirtualCall (C++)
447"""""""""""""""""""""""""""""""""
448Check virtual function calls during construction or destruction.
449
450.. code-block:: cpp
451
452 class A {
453 public:
454 A() {
455 f(); // warn
456 }
457 virtual void f();
458 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000459
Kristof Umann1a170322019-02-05 00:39:33 +0000460 class A {
461 public:
462 ~A() {
463 this->f(); // warn
464 }
465 virtual void f();
466 };
467
468optin.mpi.MPI-Checker (C)
469"""""""""""""""""""""""""
470Checks MPI code.
471
472.. code-block:: c
473
474 void test() {
475 double buf = 0;
476 MPI_Request sendReq1;
477 MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM,
478 0, MPI_COMM_WORLD, &sendReq1);
479 } // warn: request 'sendReq1' has no matching wait.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000480
Kristof Umann1a170322019-02-05 00:39:33 +0000481 void test() {
482 double buf = 0;
483 MPI_Request sendReq;
484 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq);
485 MPI_Irecv(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn
486 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn
487 MPI_Wait(&sendReq, MPI_STATUS_IGNORE);
488 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000489
Kristof Umann1a170322019-02-05 00:39:33 +0000490 void missingNonBlocking() {
491 int rank = 0;
492 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
493 MPI_Request sendReq1[10][10][10];
494 MPI_Wait(&sendReq1[1][7][9], MPI_STATUS_IGNORE); // warn
495 }
496
497optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (ObjC)
498"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
499Check that NSLocalizedString macros include a comment for context.
500
501.. code-block:: objc
502
503 - (void)test {
504 NSString *string = NSLocalizedString(@"LocalizedString", nil); // warn
505 NSString *string2 = NSLocalizedString(@"LocalizedString", @" "); // warn
506 NSString *string3 = NSLocalizedStringWithDefaultValue(
507 @"LocalizedString", nil, [[NSBundle alloc] init], nil,@""); // warn
508 }
509
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000510optin.osx.cocoa.localizability.NonLocalizedStringChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000511"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
512Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings.
513
514.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000515
Kristof Umann1a170322019-02-05 00:39:33 +0000516 NSString *alarmText =
517 NSLocalizedString(@"Enabled", @"Indicates alarm is turned on");
518 if (!isEnabled) {
519 alarmText = @"Disabled";
520 }
521 UILabel *alarmStateLabel = [[UILabel alloc] init];
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000522
Kristof Umann1a170322019-02-05 00:39:33 +0000523 // Warning: User-facing text should use localized string macro
524 [alarmStateLabel setText:alarmText];
525
526optin.performance.GCDAntipattern
527""""""""""""""""""""""""""""""""
528Check for performance anti-patterns when using Grand Central Dispatch.
529
530optin.performance.Padding
531"""""""""""""""""""""""""
532Check for excessively padded structs.
533
534optin.portability.UnixAPI
535"""""""""""""""""""""""""
536Finds implementation-defined behavior in UNIX/Posix functions.
537
538
539.. _security-checkers:
540
541security
542^^^^^^^^
543
544Security related checkers.
545
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000546security.FloatLoopCounter (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000547"""""""""""""""""""""""""""""
548Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP).
549
550.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000551
Kristof Umann1a170322019-02-05 00:39:33 +0000552 void test() {
553 for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // warn
554 }
555
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000556security.insecureAPI.UncheckedReturn (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000557""""""""""""""""""""""""""""""""""""""""
558Warn on uses of functions whose return values must be always checked.
559
560.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000561
Kristof Umann1a170322019-02-05 00:39:33 +0000562 void test() {
563 setuid(1); // warn
564 }
565
566security.insecureAPI.bcmp (C)
567"""""""""""""""""""""""""""""
568Warn on uses of the 'bcmp' function.
569
570.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000571
Kristof Umann1a170322019-02-05 00:39:33 +0000572 void test() {
573 bcmp(ptr0, ptr1, n); // warn
574 }
575
576security.insecureAPI.bcopy (C)
577""""""""""""""""""""""""""""""
578Warn on uses of the 'bcopy' function.
579
580.. code-block:: c
581
582 void test() {
583 bcopy(src, dst, n); // warn
584 }
585
586security.insecureAPI.bzero (C)
587""""""""""""""""""""""""""""""
588Warn on uses of the 'bzero' function.
589
590.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000591
Kristof Umann1a170322019-02-05 00:39:33 +0000592 void test() {
593 bzero(ptr, n); // warn
594 }
595
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000596security.insecureAPI.getpw (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000597""""""""""""""""""""""""""""""
598Warn on uses of the 'getpw' function.
599
600.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000601
Kristof Umann1a170322019-02-05 00:39:33 +0000602 void test() {
603 char buff[1024];
604 getpw(2, buff); // warn
605 }
606
607security.insecureAPI.gets (C)
608"""""""""""""""""""""""""""""
609Warn on uses of the 'gets' function.
610
611.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000612
Kristof Umann1a170322019-02-05 00:39:33 +0000613 void test() {
614 char buff[1024];
615 gets(buff); // warn
616 }
617
618security.insecureAPI.mkstemp (C)
619""""""""""""""""""""""""""""""""
620Warn when 'mkstemp' is passed fewer than 6 X's in the format string.
621
622.. code-block:: c
623
624 void test() {
625 mkstemp("XX"); // warn
626 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000627
628security.insecureAPI.mktemp (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000629"""""""""""""""""""""""""""""""
630Warn on uses of the ``mktemp`` function.
631
632.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000633
Kristof Umann1a170322019-02-05 00:39:33 +0000634 void test() {
635 char *x = mktemp("/tmp/zxcv"); // warn: insecure, use mkstemp
636 }
637
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000638security.insecureAPI.rand (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000639"""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000640Warn on uses of inferior random number generating functions (only if arc4random function is available):
Kristof Umann1a170322019-02-05 00:39:33 +0000641``drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, random, rand_r``.
642
643.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000644
Kristof Umann1a170322019-02-05 00:39:33 +0000645 void test() {
646 random(); // warn
647 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000648
Kristof Umann1a170322019-02-05 00:39:33 +0000649security.insecureAPI.strcpy (C)
650"""""""""""""""""""""""""""""""
651Warn on uses of the ``strcpy`` and ``strcat`` functions.
652
653.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000654
Kristof Umann1a170322019-02-05 00:39:33 +0000655 void test() {
656 char x[4];
657 char *y = "abcd";
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000658
Kristof Umann1a170322019-02-05 00:39:33 +0000659 strcpy(x, y); // warn
660 }
661
662
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000663security.insecureAPI.vfork (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000664""""""""""""""""""""""""""""""
665 Warn on uses of the 'vfork' function.
666
667.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000668
Kristof Umann1a170322019-02-05 00:39:33 +0000669 void test() {
670 vfork(); // warn
671 }
672
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000673security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C)
674"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Kristof Umann8d239992019-02-11 13:46:43 +0000675 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``
676
677.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000678
Kristof Umann8d239992019-02-11 13:46:43 +0000679 void test() {
680 char buf [5];
681 strncpy(buf, "a", 1); // warn
682 }
683
Kristof Umann1a170322019-02-05 00:39:33 +0000684.. _unix-checkers:
685
686unix
687^^^^
688POSIX/Unix checkers.
689
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000690unix.API (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000691""""""""""""
692Check calls to various UNIX/Posix functions: ``open, pthread_once, calloc, malloc, realloc, alloca``.
693
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000694.. literalinclude:: checkers/unix_api_example.c
Kristof Umann1a170322019-02-05 00:39:33 +0000695 :language: c
696
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000697unix.Malloc (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000698"""""""""""""""
699Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().
700
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000701.. literalinclude:: checkers/unix_malloc_example.c
Kristof Umann1a170322019-02-05 00:39:33 +0000702 :language: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000703
704unix.MallocSizeof (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000705"""""""""""""""""""""
706Check for dubious ``malloc`` arguments involving ``sizeof``.
707
708.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000709
Kristof Umann1a170322019-02-05 00:39:33 +0000710 void test() {
711 long *p = malloc(sizeof(short));
712 // warn: result is converted to 'long *', which is
713 // incompatible with operand type 'short'
714 free(p);
715 }
716
717unix.MismatchedDeallocator (C, C++)
718"""""""""""""""""""""""""""""""""""
719Check for mismatched deallocators.
720
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000721.. literalinclude:: checkers/mismatched_deallocator_example.cpp
Kristof Umann1a170322019-02-05 00:39:33 +0000722 :language: c
723
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000724unix.Vfork (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000725""""""""""""""
726Check for proper usage of ``vfork``.
727
728.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000729
Kristof Umann1a170322019-02-05 00:39:33 +0000730 int test(int x) {
731 pid_t pid = vfork(); // warn
732 if (pid != 0)
733 return 0;
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000734
Kristof Umann1a170322019-02-05 00:39:33 +0000735 switch (x) {
736 case 0:
737 pid = 1;
738 execl("", "", 0);
739 _exit(1);
740 break;
741 case 1:
742 x = 0; // warn: this assignment is prohibited
743 break;
744 case 2:
745 foo(); // warn: this function call is prohibited
746 break;
747 default:
748 return 0; // warn: return is prohibited
749 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000750
Kristof Umann1a170322019-02-05 00:39:33 +0000751 while(1);
752 }
753
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000754unix.cstring.BadSizeArg (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000755"""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000756Check 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 +0000757
758.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000759
Kristof Umann1a170322019-02-05 00:39:33 +0000760 void test() {
761 char dest[3];
762 strncat(dest, """""""""""""""""""""""""*", sizeof(dest));
763 // warn: potential buffer overflow
764 }
765
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000766unix.cstrisng.NullArg (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000767"""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000768Check for null pointers being passed as arguments to C string functions:
Kristof Umann1a170322019-02-05 00:39:33 +0000769``strlen, strnlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp``.
770
771.. code-block:: c
772
773 int test() {
774 return strlen(0); // warn
775 }
776
777.. _osx-checkers:
778
779osx
780^^^
781OS X checkers.
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000782
783osx.API (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000784"""""""""""
785Check for proper uses of various Apple APIs.
786
787.. code-block:: objc
788
789 void test() {
790 dispatch_once_t pred = 0;
791 dispatch_once(&pred, ^(){}); // warn: dispatch_once uses local
792 }
793
794osx.NumberObjectConversion (C, C++, ObjC)
795"""""""""""""""""""""""""""""""""""""""""
796Check for erroneous conversions of objects representing numbers into numbers.
797
798.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000799
Kristof Umann1a170322019-02-05 00:39:33 +0000800 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"];
801 // Warning: Comparing a pointer value of type 'NSNumber *'
802 // to a scalar integer value
803 if (photoCount > 0) {
804 [self displayPhotos];
805 }
806
807osx.ObjCProperty (ObjC)
808"""""""""""""""""""""""
809Check for proper uses of Objective-C properties.
810
811.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000812
Kristof Umann1a170322019-02-05 00:39:33 +0000813 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"];
814 // Warning: Comparing a pointer value of type 'NSNumber *'
815 // to a scalar integer value
816 if (photoCount > 0) {
817 [self displayPhotos];
818 }
819
820
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000821osx.SecKeychainAPI (C)
Kristof Umann1a170322019-02-05 00:39:33 +0000822""""""""""""""""""""""
823Check for proper uses of Secure Keychain APIs.
824
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000825.. literalinclude:: checkers/seckeychainapi_example.m
Kristof Umann1a170322019-02-05 00:39:33 +0000826 :language: objc
827
828osx.cocoa.AtSync (ObjC)
829"""""""""""""""""""""""
830Check for nil pointers used as mutexes for @synchronized.
831
832.. code-block:: objc
833
834 void test(id x) {
835 if (!x)
836 @synchronized(x) {} // warn: nil value used as mutex
837 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000838
Kristof Umann1a170322019-02-05 00:39:33 +0000839 void test() {
840 id y;
841 @synchronized(y) {} // warn: uninitialized value used as mutex
842 }
843
844osx.cocoa.AutoreleaseWrite
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000845""""""""""""""""""""""""""
Kristof Umann1a170322019-02-05 00:39:33 +0000846Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C.
847
848osx.cocoa.ClassRelease (ObjC)
849"""""""""""""""""""""""""""""
850Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
851
852.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000853
Kristof Umann1a170322019-02-05 00:39:33 +0000854 @interface MyClass : NSObject
855 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000856
Kristof Umann1a170322019-02-05 00:39:33 +0000857 void test(void) {
858 [MyClass release]; // warn
859 }
860
861osx.cocoa.Dealloc (ObjC)
862""""""""""""""""""""""""
863Warn about Objective-C classes that lack a correct implementation of -dealloc
864
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000865.. literalinclude:: checkers/dealloc_example.m
Kristof Umann1a170322019-02-05 00:39:33 +0000866 :language: objc
867
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000868osx.cocoa.IncompatibleMethodTypes (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000869""""""""""""""""""""""""""""""""""""""""
870Warn about Objective-C method signatures with type incompatibilities.
871
872.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000873
Kristof Umann1a170322019-02-05 00:39:33 +0000874 @interface MyClass1 : NSObject
875 - (int)foo;
876 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000877
Kristof Umann1a170322019-02-05 00:39:33 +0000878 @implementation MyClass1
879 - (int)foo { return 1; }
880 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000881
Kristof Umann1a170322019-02-05 00:39:33 +0000882 @interface MyClass2 : MyClass1
883 - (float)foo;
884 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000885
Kristof Umann1a170322019-02-05 00:39:33 +0000886 @implementation MyClass2
887 - (float)foo { return 1.0; } // warn
888 @end
889
890osx.cocoa.Loops
891"""""""""""""""
892Improved modeling of loops using Cocoa collection types.
893
894osx.cocoa.MissingSuperCall (ObjC)
895"""""""""""""""""""""""""""""""""
896Warn about Objective-C methods that lack a necessary call to super.
897
898.. code-block:: objc
899
900 @interface Test : UIViewController
901 @end
902 @implementation test
903 - (void)viewDidLoad {} // warn
904 @end
905
906
907osx.cocoa.NSAutoreleasePool (ObjC)
908""""""""""""""""""""""""""""""""""
909Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode.
910
911.. code-block:: objc
912
913 void test() {
914 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
915 [pool release]; // warn
916 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000917
918osx.cocoa.NSError (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000919""""""""""""""""""""""""
920Check usage of NSError parameters.
921
922.. code-block:: objc
923
924 @interface A : NSObject
925 - (void)foo:(NSError """""""""""""""""""""""")error;
926 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000927
Kristof Umann1a170322019-02-05 00:39:33 +0000928 @implementation A
929 - (void)foo:(NSError """""""""""""""""""""""")error {
930 // warn: method accepting NSError"""""""""""""""""""""""" should have a non-void
931 // return value
932 }
933 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000934
Kristof Umann1a170322019-02-05 00:39:33 +0000935 @interface A : NSObject
936 - (BOOL)foo:(NSError """""""""""""""""""""""")error;
937 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000938
Kristof Umann1a170322019-02-05 00:39:33 +0000939 @implementation A
940 - (BOOL)foo:(NSError """""""""""""""""""""""")error {
941 *error = 0; // warn: potential null dereference
942 return 0;
943 }
944 @end
945
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000946osx.cocoa.NilArg (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000947"""""""""""""""""""""""
948Check for prohibited nil arguments to ObjC method calls.
949
950 - caseInsensitiveCompare:
951 - compare:
952 - compare:options:
953 - compare:options:range:
954 - compare:options:range:locale:
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000955 - componentsSeparatedByCharactersInSet:
Kristof Umann1a170322019-02-05 00:39:33 +0000956 - initWithFormat:
957
958.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000959
Kristof Umann1a170322019-02-05 00:39:33 +0000960 NSComparisonResult test(NSString *s) {
961 NSString *aString = nil;
962 return [s caseInsensitiveCompare:aString];
963 // warn: argument to 'NSString' method
964 // 'caseInsensitiveCompare:' cannot be nil
965 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000966
Kristof Umann1a170322019-02-05 00:39:33 +0000967
968osx.cocoa.NonNilReturnValue
969"""""""""""""""""""""""""""
970Models the APIs that are guaranteed to return a non-nil value.
971
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000972osx.cocoa.ObjCGenerics (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000973"""""""""""""""""""""""""""""
974Check for type errors when using Objective-C generics.
975
976.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000977
Kristof Umann1a170322019-02-05 00:39:33 +0000978 NSMutableArray *names = [NSMutableArray array];
979 NSMutableArray *birthDates = names;
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000980
Kristof Umann1a170322019-02-05 00:39:33 +0000981 // Warning: Conversion from value of type 'NSDate *'
982 // to incompatible type 'NSString *'
983 [birthDates addObject: [NSDate date]];
984
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000985osx.cocoa.RetainCount (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +0000986""""""""""""""""""""""""""""
987Check for leaks and improper reference count management
988
989.. code-block:: objc
990
991 void test() {
992 NSString *s = [[NSString alloc] init]; // warn
993 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +0000994
Kristof Umann1a170322019-02-05 00:39:33 +0000995 CFStringRef test(char *bytes) {
996 return CFStringCreateWithCStringNoCopy(
997 0, bytes, NSNEXTSTEPStringEncoding, 0); // warn
998 }
999
1000
1001osx.cocoa.RunLoopAutoreleaseLeak
1002""""""""""""""""""""""""""""""""
1003Check for leaked memory in autorelease pools that will never be drained.
1004
1005osx.cocoa.SelfInit (ObjC)
1006"""""""""""""""""""""""""
1007Check that 'self' is properly initialized inside an initializer method.
1008
1009.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001010
Kristof Umann1a170322019-02-05 00:39:33 +00001011 @interface MyObj : NSObject {
1012 id x;
1013 }
1014 - (id)init;
1015 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001016
Kristof Umann1a170322019-02-05 00:39:33 +00001017 @implementation MyObj
1018 - (id)init {
1019 [super init];
1020 x = 0; // warn: instance variable used while 'self' is not
1021 // initialized
1022 return 0;
1023 }
1024 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001025
Kristof Umann1a170322019-02-05 00:39:33 +00001026 @interface MyObj : NSObject
1027 - (id)init;
1028 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001029
Kristof Umann1a170322019-02-05 00:39:33 +00001030 @implementation MyObj
1031 - (id)init {
1032 [super init];
1033 return self; // warn: returning uninitialized 'self'
1034 }
1035 @end
1036
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001037osx.cocoa.SuperDealloc (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001038"""""""""""""""""""""""""""""
1039Warn about improper use of '[super dealloc]' in Objective-C.
1040
1041.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001042
Kristof Umann1a170322019-02-05 00:39:33 +00001043 @interface SuperDeallocThenReleaseIvarClass : NSObject {
1044 NSObject *_ivar;
1045 }
1046 @end
1047
1048 @implementation SuperDeallocThenReleaseIvarClass
1049 - (void)dealloc {
1050 [super dealloc];
1051 [_ivar release]; // warn
1052 }
1053 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001054
Kristof Umann1a170322019-02-05 00:39:33 +00001055osx.cocoa.UnusedIvars (ObjC)
1056""""""""""""""""""""""""""""
1057Warn about private ivars that are never used.
1058
1059.. code-block:: objc
1060
1061 @interface MyObj : NSObject {
1062 @private
1063 id x; // warn
1064 }
1065 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001066
Kristof Umann1a170322019-02-05 00:39:33 +00001067 @implementation MyObj
1068 @end
1069
1070osx.cocoa.VariadicMethodTypes (ObjC)
1071""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001072Check for passing non-Objective-C types to variadic collection
Kristof Umann1a170322019-02-05 00:39:33 +00001073initialization methods that expect only Objective-C types.
1074
1075.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001076
Kristof Umann1a170322019-02-05 00:39:33 +00001077 void test() {
1078 [NSSet setWithObjects:@"Foo", "Bar", nil];
1079 // warn: argument should be an ObjC pointer type, not 'char *'
1080 }
1081
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001082osx.coreFoundation.CFError (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001083""""""""""""""""""""""""""""""
1084Check usage of CFErrorRef* parameters
1085
1086.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001087
Kristof Umann1a170322019-02-05 00:39:33 +00001088 void test(CFErrorRef *error) {
1089 // warn: function accepting CFErrorRef* should have a
1090 // non-void return
1091 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001092
Kristof Umann1a170322019-02-05 00:39:33 +00001093 int foo(CFErrorRef *error) {
1094 *error = 0; // warn: potential null dereference
1095 return 0;
1096 }
1097
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001098osx.coreFoundation.CFNumber (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001099"""""""""""""""""""""""""""""""
1100Check for proper uses of CFNumber APIs.
1101
1102.. code-block:: c
1103
1104 CFNumberRef test(unsigned char x) {
1105 return CFNumberCreate(0, kCFNumberSInt16Type, &x);
1106 // warn: 8 bit integer is used to initialize a 16 bit integer
1107 }
1108
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001109osx.coreFoundation.CFRetainRelease (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001110""""""""""""""""""""""""""""""""""""""
1111Check for null arguments to CFRetain/CFRelease/CFMakeCollectable.
1112
1113.. code-block:: c
1114
1115 void test(CFTypeRef p) {
1116 if (!p)
1117 CFRetain(p); // warn
1118 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001119
Kristof Umann1a170322019-02-05 00:39:33 +00001120 void test(int x, CFTypeRef p) {
1121 if (p)
1122 return;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001123
Kristof Umann1a170322019-02-05 00:39:33 +00001124 CFRelease(p); // warn
1125 }
1126
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001127osx.coreFoundation.containers.OutOfBounds (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001128"""""""""""""""""""""""""""""""""""""""""""""
1129Checks for index out-of-bounds when using 'CFArray' API.
1130
1131.. code-block:: c
1132
1133 void test() {
1134 CFArrayRef A = CFArrayCreate(0, 0, 0, &kCFTypeArrayCallBacks);
1135 CFArrayGetValueAtIndex(A, 0); // warn
1136 }
1137
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001138osx.coreFoundation.containers.PointerSizedValues (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001139""""""""""""""""""""""""""""""""""""""""""""""""""""
1140Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values.
1141
1142.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001143
Kristof Umann1a170322019-02-05 00:39:33 +00001144 void test() {
1145 int x[] = { 1 };
1146 CFArrayRef A = CFArrayCreate(0, (const void """""""""""""""""""""""")x, 1,
1147 &kCFTypeArrayCallBacks); // warn
1148 }
1149
1150
1151.. _alpha-checkers:
1152
1153Experimental Checkers
1154---------------------
1155
1156*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.*
1157
1158alpha.clone
1159^^^^^^^^^^^
1160
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001161alpha.clone.CloneChecker (C, C++, ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001162"""""""""""""""""""""""""""""""""""""""
1163Reports similar pieces of code.
1164
1165.. code-block:: c
1166
1167 void log();
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001168
Kristof Umann1a170322019-02-05 00:39:33 +00001169 int max(int a, int b) { // warn
1170 log();
1171 if (a > b)
1172 return a;
1173 return b;
1174 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001175
Kristof Umann1a170322019-02-05 00:39:33 +00001176 int maxClone(int x, int y) { // similar code here
1177 log();
1178 if (x > y)
1179 return x;
1180 return y;
1181 }
1182
1183alpha.core.BoolAssignment (ObjC)
1184""""""""""""""""""""""""""""""""
1185Warn about assigning non-{0,1} values to boolean variables.
1186
1187.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001188
Kristof Umann1a170322019-02-05 00:39:33 +00001189 void test() {
1190 BOOL b = -1; // warn
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001191 }
Kristof Umann1a170322019-02-05 00:39:33 +00001192
1193alpha.core
1194^^^^^^^^^^
1195
1196alpha.core.CallAndMessageUnInitRefArg (C,C++, ObjC)
1197"""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001198Check for logical errors for function calls and Objective-C
Kristof Umann1a170322019-02-05 00:39:33 +00001199message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables).
1200
1201.. code-block:: c
1202
1203 void test(void) {
1204 int t;
1205 int &p = t;
1206 int &s = p;
1207 int &q = s;
1208 foo(q); // warn
1209 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001210
Kristof Umann1a170322019-02-05 00:39:33 +00001211 void test(void) {
1212 int x;
1213 foo(&x); // warn
1214 }
1215
1216alpha.core.CastSize (C)
1217"""""""""""""""""""""""
1218Check when casting a malloc'ed type ``T``, whether the size is a multiple of the size of ``T``.
1219
1220.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001221
Kristof Umann1a170322019-02-05 00:39:33 +00001222 void test() {
1223 int *x = (int *) malloc(11); // warn
1224 }
1225
1226alpha.core.CastToStruct (C, C++)
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001227""""""""""""""""""""""""""""""""
Kristof Umann1a170322019-02-05 00:39:33 +00001228Check for cast from non-struct pointer to struct pointer.
1229
1230.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001231
Kristof Umann1a170322019-02-05 00:39:33 +00001232 // C
1233 struct s {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001234
Kristof Umann1a170322019-02-05 00:39:33 +00001235 void test(int *p) {
1236 struct s *ps = (struct s *) p; // warn
1237 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001238
Kristof Umann1a170322019-02-05 00:39:33 +00001239 // C++
1240 class c {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001241
Kristof Umann1a170322019-02-05 00:39:33 +00001242 void test(int *p) {
1243 c *pc = (c *) p; // warn
1244 }
1245
1246alpha.core.Conversion (C, C++, ObjC)
1247""""""""""""""""""""""""""""""""""""
1248Loss of sign/precision in implicit conversions.
1249
1250.. code-block:: c
1251
1252 void test(unsigned U, signed S) {
1253 if (S > 10) {
1254 if (U < S) {
1255 }
1256 }
1257 if (S < -10) {
1258 if (U < S) { // warn (loss of sign)
1259 }
1260 }
1261 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001262
Kristof Umann1a170322019-02-05 00:39:33 +00001263 void test() {
1264 long long A = 1LL << 60;
1265 short X = A; // warn (loss of precision)
1266 }
1267
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001268alpha.core.DynamicTypeChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001269""""""""""""""""""""""""""""""""""""
1270Check for cases where the dynamic and the static type of an object are unrelated.
1271
1272
1273.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001274
Kristof Umann1a170322019-02-05 00:39:33 +00001275 id date = [NSDate date];
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001276
Kristof Umann1a170322019-02-05 00:39:33 +00001277 // Warning: Object has a dynamic type 'NSDate *' which is
1278 // incompatible with static type 'NSNumber *'"
1279 NSNumber *number = date;
1280 [number doubleValue];
1281
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001282alpha.core.FixedAddr (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001283""""""""""""""""""""""""
1284Check for assignment of a fixed address to a pointer.
1285
1286.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001287
Kristof Umann1a170322019-02-05 00:39:33 +00001288 void test() {
1289 int *p;
1290 p = (int *) 0x10000; // warn
1291 }
1292
1293alpha.core.IdenticalExpr (C, C++)
1294"""""""""""""""""""""""""""""""""
1295Warn about unintended use of identical expressions in operators.
1296
1297.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001298
Kristof Umann1a170322019-02-05 00:39:33 +00001299 // C
1300 void test() {
1301 int a = 5;
1302 int b = a | 4 | a; // warn: identical expr on both sides
1303 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001304
Kristof Umann1a170322019-02-05 00:39:33 +00001305 // C++
1306 bool f(void);
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001307
Kristof Umann1a170322019-02-05 00:39:33 +00001308 void test(bool b) {
1309 int i = 10;
1310 if (f()) { // warn: true and false branches are identical
1311 do {
1312 i--;
1313 } while (f());
1314 } else {
1315 do {
1316 i--;
1317 } while (f());
1318 }
1319 }
1320
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001321alpha.core.PointerArithm (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001322""""""""""""""""""""""""""""
1323Check for pointer arithmetic on locations other than array elements.
1324
1325.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001326
Kristof Umann1a170322019-02-05 00:39:33 +00001327 void test() {
1328 int x;
1329 int *p;
1330 p = &x + 1; // warn
1331 }
1332
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001333alpha.core.PointerSub (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001334"""""""""""""""""""""""""
1335Check for pointer subtractions on two pointers pointing to different memory chunks.
1336
1337.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001338
Kristof Umann1a170322019-02-05 00:39:33 +00001339 void test() {
1340 int x, y;
1341 int d = &y - &x; // warn
1342 }
1343
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001344alpha.core.SizeofPtr (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001345""""""""""""""""""""""""
1346Warn about unintended use of ``sizeof()`` on pointer expressions.
1347
1348.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001349
Kristof Umann1a170322019-02-05 00:39:33 +00001350 struct s {};
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001351
Kristof Umann1a170322019-02-05 00:39:33 +00001352 int test(struct s *p) {
1353 return sizeof(p);
1354 // warn: sizeof(ptr) can produce an unexpected result
1355 }
1356
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001357alpha.core.StackAddressAsyncEscape (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001358""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001359Check that addresses to stack memory do not escape the function that involves dispatch_after or dispatch_async.
Kristof Umann1a170322019-02-05 00:39:33 +00001360This checker is a part of ``core.StackAddressEscape``, but is temporarily disabled until some false positives are fixed.
1361
1362.. code-block:: c
1363
1364 dispatch_block_t test_block_inside_block_async_leak() {
1365 int x = 123;
1366 void (^inner)(void) = ^void(void) {
1367 int y = x;
1368 ++y;
1369 };
1370 void (^outer)(void) = ^void(void) {
1371 int z = x;
1372 ++z;
1373 inner();
1374 };
1375 return outer; // warn: address of stack-allocated block is captured by a
1376 // returned block
1377 }
1378
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001379alpha.core.TestAfterDivZero (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001380"""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001381Check for division by variable that is later compared against 0.
Kristof Umann1a170322019-02-05 00:39:33 +00001382Either the comparison is useless or there is division by zero.
1383
1384.. code-block:: c
1385
1386 void test(int x) {
1387 var = 77 / x;
1388 if (x == 0) { } // warn
1389 }
1390
1391alpha.cplusplus
1392^^^^^^^^^^^^^^^
1393
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001394alpha.cplusplus.DeleteWithNonVirtualDtor (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001395""""""""""""""""""""""""""""""""""""""""""""""
1396Reports destructions of polymorphic objects with a non-virtual destructor in their base class.
1397
1398.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001399
Kristof Umann1a170322019-02-05 00:39:33 +00001400 NonVirtual *create() {
1401 NonVirtual *x = new NVDerived(); // note: conversion from derived to base
1402 // happened here
1403 return x;
1404 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001405
Kristof Umann1a170322019-02-05 00:39:33 +00001406 void sink(NonVirtual *x) {
1407 delete x; // warn: destruction of a polymorphic object with no virtual
1408 // destructor
1409 }
1410
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001411alpha.cplusplus.EnumCastOutOfRange (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001412""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001413Check for integer to enumeration casts that could result in undefined values.
Kristof Umann1a170322019-02-05 00:39:33 +00001414
1415.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001416
Kristof Umann1a170322019-02-05 00:39:33 +00001417 enum TestEnum {
1418 A = 0
1419 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001420
Kristof Umann1a170322019-02-05 00:39:33 +00001421 void foo() {
1422 TestEnum t = static_cast(-1);
1423 // warn: the value provided to the cast expression is not in
1424 the valid range of values for the enum
1425
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001426alpha.cplusplus.InvalidatedIterator (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001427"""""""""""""""""""""""""""""""""""""""""
1428Check for use of invalidated iterators.
1429
1430.. code-block:: cpp
1431
1432 void bad_copy_assign_operator_list1(std::list &L1,
1433 const std::list &L2) {
1434 auto i0 = L1.cbegin();
1435 L1 = L2;
1436 *i0; // warn: invalidated iterator accessed
1437 }
1438
1439
1440alpha.cplusplus.IteratorRange (C++)
1441"""""""""""""""""""""""""""""""""""
1442Check for iterators used outside their valid ranges.
1443
1444.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001445
Kristof Umann1a170322019-02-05 00:39:33 +00001446 void simple_bad_end(const std::vector &v) {
1447 auto i = v.end();
1448 *i; // warn: iterator accessed outside of its range
1449 }
1450
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001451alpha.cplusplus.MismatchedIterator (C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001452""""""""""""""""""""""""""""""""""""""""
1453Check for use of iterators of different containers where iterators of the same container are expected.
1454
1455.. code-block:: cpp
1456
1457 void bad_insert3(std::vector &v1, std::vector &v2) {
1458 v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed
1459 // using foreign
1460 // iterator argument
1461 v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of
1462 // different containers
1463 // used where the same
1464 // container is
1465 // expected
1466 v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of
1467 // different containers
1468 // used where the same
1469 // container is
1470 // expected
1471 }
1472
1473alpha.cplusplus.MisusedMovedObject (C++)
1474""""""""""""""""""""""""""""""""""""""""
1475Method calls on a moved-from object and copying a moved-from object will be reported.
1476
1477
1478.. code-block:: cpp
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001479
Kristof Umann1a170322019-02-05 00:39:33 +00001480 struct A {
1481 void foo() {}
1482 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001483
Kristof Umann1a170322019-02-05 00:39:33 +00001484 void f() {
1485 A a;
1486 A b = std::move(a); // note: 'a' became 'moved-from' here
1487 a.foo(); // warn: method call on a 'moved-from' object 'a'
1488 }
1489
Kristof Umann1a170322019-02-05 00:39:33 +00001490alpha.deadcode
1491^^^^^^^^^^^^^^
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001492alpha.deadcode.UnreachableCode (C, C++)
Kristof Umann1a170322019-02-05 00:39:33 +00001493"""""""""""""""""""""""""""""""""""""""
1494Check unreachable code.
1495
1496.. code-block:: cpp
1497
1498 // C
1499 int test() {
1500 int x = 1;
1501 while(x);
1502 return x; // warn
1503 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001504
Kristof Umann1a170322019-02-05 00:39:33 +00001505 // C++
1506 void test() {
1507 int a = 2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001508
Kristof Umann1a170322019-02-05 00:39:33 +00001509 while (a > 1)
1510 a--;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001511
Kristof Umann1a170322019-02-05 00:39:33 +00001512 if (a > 1)
1513 a++; // warn
1514 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001515
Kristof Umann1a170322019-02-05 00:39:33 +00001516 // Objective-C
1517 void test(id x) {
1518 return;
1519 [x retain]; // warn
1520 }
1521
1522alpha.llvm
1523^^^^^^^^^^
1524
1525alpha.llvm.Conventions
1526""""""""""""""""""""""
1527
1528Check code for LLVM codebase conventions:
1529
1530* A StringRef should not be bound to a temporary std::string whose lifetime is shorter than the StringRef's.
1531* Clang AST nodes should not have fields that can allocate memory.
1532
1533
1534alpha.osx
1535^^^^^^^^^
1536
1537alpha.osx.cocoa.DirectIvarAssignment (ObjC)
1538"""""""""""""""""""""""""""""""""""""""""""
1539Check for direct assignments to instance variables.
1540
1541
1542.. code-block:: objc
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001543
Kristof Umann1a170322019-02-05 00:39:33 +00001544 @interface MyClass : NSObject {}
1545 @property (readonly) id A;
1546 - (void) foo;
1547 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001548
Kristof Umann1a170322019-02-05 00:39:33 +00001549 @implementation MyClass
1550 - (void) foo {
1551 _A = 0; // warn
1552 }
1553 @end
1554
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001555alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001556""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001557Check for direct assignments to instance variables in
Kristof Umann1a170322019-02-05 00:39:33 +00001558the methods annotated with ``objc_no_direct_instance_variable_assignment``.
1559
1560.. code-block:: objc
1561
1562 @interface MyClass : NSObject {}
1563 @property (readonly) id A;
1564 - (void) fAnnotated __attribute__((
1565 annotate("objc_no_direct_instance_variable_assignment")));
1566 - (void) fNotAnnotated;
1567 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001568
Kristof Umann1a170322019-02-05 00:39:33 +00001569 @implementation MyClass
1570 - (void) fAnnotated {
1571 _A = 0; // warn
1572 }
1573 - (void) fNotAnnotated {
1574 _A = 0; // no warn
1575 }
1576 @end
1577
1578
1579alpha.osx.cocoa.InstanceVariableInvalidation (ObjC)
1580"""""""""""""""""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001581Check that the invalidatable instance variables are
Kristof Umann1a170322019-02-05 00:39:33 +00001582invalidated in the methods annotated with objc_instance_variable_invalidator.
1583
1584.. code-block:: objc
1585
1586 @protocol Invalidation <NSObject>
1587 - (void) invalidate
1588 __attribute__((annotate("objc_instance_variable_invalidator")));
1589 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001590
Kristof Umann1a170322019-02-05 00:39:33 +00001591 @interface InvalidationImpObj : NSObject <Invalidation>
1592 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001593
Kristof Umann1a170322019-02-05 00:39:33 +00001594 @interface SubclassInvalidationImpObj : InvalidationImpObj {
1595 InvalidationImpObj *var;
1596 }
1597 - (void)invalidate;
1598 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001599
Kristof Umann1a170322019-02-05 00:39:33 +00001600 @implementation SubclassInvalidationImpObj
1601 - (void) invalidate {}
1602 @end
1603 // warn: var needs to be invalidated or set to nil
1604
1605alpha.osx.cocoa.MissingInvalidationMethod (ObjC)
1606""""""""""""""""""""""""""""""""""""""""""""""""
1607Check that the invalidation methods are present in classes that contain invalidatable instance variables.
1608
1609.. code-block:: objc
1610
1611 @protocol Invalidation <NSObject>
1612 - (void)invalidate
1613 __attribute__((annotate("objc_instance_variable_invalidator")));
1614 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001615
Kristof Umann1a170322019-02-05 00:39:33 +00001616 @interface NeedInvalidation : NSObject <Invalidation>
1617 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001618
Kristof Umann1a170322019-02-05 00:39:33 +00001619 @interface MissingInvalidationMethodDecl : NSObject {
1620 NeedInvalidation *Var; // warn
1621 }
1622 @end
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001623
Kristof Umann1a170322019-02-05 00:39:33 +00001624 @implementation MissingInvalidationMethodDecl
1625 @end
1626
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001627alpha.osx.cocoa.localizability.PluralMisuseChecker (ObjC)
Kristof Umann1a170322019-02-05 00:39:33 +00001628"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1629Warns against using one vs. many plural pattern in code when generating localized strings.
1630
1631.. code-block:: objc
1632
1633 NSString *reminderText =
1634 NSLocalizedString(@"None", @"Indicates no reminders");
1635 if (reminderCount == 1) {
1636 // Warning: Plural cases are not supported across all languages.
1637 // Use a .stringsdict file instead
1638 reminderText =
1639 NSLocalizedString(@"1 Reminder", @"Indicates single reminder");
1640 } else if (reminderCount >= 2) {
1641 // Warning: Plural cases are not supported across all languages.
1642 // Use a .stringsdict file instead
1643 reminderText =
1644 [NSString stringWithFormat:
1645 NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"),
1646 reminderCount];
1647 }
1648
1649alpha.security
1650^^^^^^^^^^^^^^
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001651alpha.security.ArrayBound (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001652"""""""""""""""""""""""""""""
1653Warn about buffer overflows (older checker).
1654
1655.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001656
Kristof Umann1a170322019-02-05 00:39:33 +00001657 void test() {
1658 char *s = "";
1659 char c = s[1]; // warn
1660 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001661
Kristof Umann1a170322019-02-05 00:39:33 +00001662 struct seven_words {
1663 int c[7];
1664 };
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001665
Kristof Umann1a170322019-02-05 00:39:33 +00001666 void test() {
1667 struct seven_words a, *p;
1668 p = &a;
1669 p[0] = a;
1670 p[1] = a;
1671 p[2] = a; // warn
1672 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001673
Kristof Umann1a170322019-02-05 00:39:33 +00001674 // note: requires unix.Malloc or
1675 // alpha.unix.MallocWithAnnotations checks enabled.
1676 void test() {
1677 int *p = malloc(12);
1678 p[3] = 4; // warn
1679 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001680
Kristof Umann1a170322019-02-05 00:39:33 +00001681 void test() {
1682 char a[2];
1683 int *b = (int*)a;
1684 b[1] = 3; // warn
1685 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001686
1687alpha.security.ArrayBoundV2 (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001688"""""""""""""""""""""""""""""""
1689Warn about buffer overflows (newer checker).
1690
1691.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001692
Kristof Umann1a170322019-02-05 00:39:33 +00001693 void test() {
1694 char *s = "";
1695 char c = s[1]; // warn
1696 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001697
Kristof Umann1a170322019-02-05 00:39:33 +00001698 void test() {
1699 int buf[100];
1700 int *p = buf;
1701 p = p + 99;
1702 p[1] = 1; // warn
1703 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001704
Kristof Umann1a170322019-02-05 00:39:33 +00001705 // note: compiler has internal check for this.
1706 // Use -Wno-array-bounds to suppress compiler warning.
1707 void test() {
1708 int buf[100][100];
1709 buf[0][-1] = 1; // warn
1710 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001711
Kristof Umann1a170322019-02-05 00:39:33 +00001712 // note: requires alpha.security.taint check turned on.
1713 void test() {
1714 char s[] = "abc";
1715 int x = getchar();
1716 char c = s[x]; // warn: index is tainted
1717 }
1718
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001719alpha.security.MallocOverflow (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001720"""""""""""""""""""""""""""""""""
1721Check for overflows in the arguments to malloc().
1722
1723.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001724
Kristof Umann1a170322019-02-05 00:39:33 +00001725 void test(int n) {
1726 void *p = malloc(n * sizeof(int)); // warn
1727 }
1728
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001729alpha.security.MmapWriteExec (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001730""""""""""""""""""""""""""""""""
1731Warn on mmap() calls that are both writable and executable.
1732
1733.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001734
Kristof Umann1a170322019-02-05 00:39:33 +00001735 void test(int n) {
1736 void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC,
1737 MAP_PRIVATE | MAP_ANON, -1, 0);
1738 // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to
1739 // exploitable memory regions, which could be overwritten with malicious
1740 // code
1741 }
1742
1743alpha.security.ReturnPtrRange (C)
1744"""""""""""""""""""""""""""""""""
1745Check for an out-of-bound pointer being returned to callers.
1746
1747.. code-block:: c
1748
1749 static int A[10];
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001750
Kristof Umann1a170322019-02-05 00:39:33 +00001751 int *test() {
1752 int *p = A + 10;
1753 return p; // warn
1754 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001755
Kristof Umann1a170322019-02-05 00:39:33 +00001756 int test(void) {
1757 int x;
1758 return x; // warn: undefined or garbage returned
1759 }
1760
1761alpha.security.taint.TaintPropagation (C, C++)
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001762""""""""""""""""""""""""""""""""""""""""""""""
1763Generate taint information used by other checkers.
Kristof Umann1a170322019-02-05 00:39:33 +00001764A data is tainted when it comes from an unreliable source.
1765
1766.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001767
Kristof Umann1a170322019-02-05 00:39:33 +00001768 void test() {
1769 char x = getchar(); // 'x' marked as tainted
1770 system(&x); // warn: untrusted data is passed to a system call
1771 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001772
Kristof Umann1a170322019-02-05 00:39:33 +00001773 // note: compiler internally checks if the second param to
1774 // sprintf is a string literal or not.
1775 // Use -Wno-format-security to suppress compiler warning.
1776 void test() {
1777 char s[10], buf[10];
1778 fscanf(stdin, "%s", s); // 's' marked as tainted
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001779
Kristof Umann1a170322019-02-05 00:39:33 +00001780 sprintf(buf, s); // warn: untrusted data as a format string
1781 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001782
Kristof Umann1a170322019-02-05 00:39:33 +00001783 void test() {
1784 size_t ts;
1785 scanf("%zd", &ts); // 'ts' marked as tainted
1786 int *p = (int *)malloc(ts * sizeof(int));
1787 // warn: untrusted data as buffer size
1788 }
1789
1790alpha.unix
1791^^^^^^^^^^^
1792
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001793alpha.unix.BlockInCriticalSection (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001794"""""""""""""""""""""""""""""""""""""
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001795Check for calls to blocking functions inside a critical section.
Kristof Umann1a170322019-02-05 00:39:33 +00001796Applies to: ``lock, unlock, sleep, getc, fgets, read, recv, pthread_mutex_lock,``
1797`` pthread_mutex_unlock, mtx_lock, mtx_timedlock, mtx_trylock, mtx_unlock, lock_guard, unique_lock``
1798
1799.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001800
Kristof Umann1a170322019-02-05 00:39:33 +00001801 void test() {
1802 std::mutex m;
1803 m.lock();
1804 sleep(3); // warn: a blocking function sleep is called inside a critical
1805 // section
1806 m.unlock();
1807 }
1808
1809alpha.unix.Chroot (C)
1810"""""""""""""""""""""
1811Check improper use of chroot.
1812
1813.. code-block:: c
1814
1815 void f();
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001816
Kristof Umann1a170322019-02-05 00:39:33 +00001817 void test() {
1818 chroot("/usr/local");
1819 f(); // warn: no call of chdir("/") immediately after chroot
1820 }
1821
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001822alpha.unix.PthreadLock (C)
Kristof Umann1a170322019-02-05 00:39:33 +00001823""""""""""""""""""""""""""
1824Simple lock -> unlock checker.
1825Applies to: ``pthread_mutex_lock, pthread_rwlock_rdlock, pthread_rwlock_wrlock, lck_mtx_lock, lck_rw_lock_exclusive``
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001826``lck_rw_lock_shared, pthread_mutex_trylock, pthread_rwlock_tryrdlock, pthread_rwlock_tryrwlock, lck_mtx_try_lock,
Kristof Umann1a170322019-02-05 00:39:33 +00001827lck_rw_try_lock_exclusive, lck_rw_try_lock_shared, pthread_mutex_unlock, pthread_rwlock_unlock, lck_mtx_unlock, lck_rw_done``.
1828
1829
1830.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001831
Kristof Umann1a170322019-02-05 00:39:33 +00001832 pthread_mutex_t mtx;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001833
Kristof Umann1a170322019-02-05 00:39:33 +00001834 void test() {
1835 pthread_mutex_lock(&mtx);
1836 pthread_mutex_lock(&mtx);
1837 // warn: this lock has already been acquired
1838 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001839
Kristof Umann1a170322019-02-05 00:39:33 +00001840 lck_mtx_t lck1, lck2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001841
Kristof Umann1a170322019-02-05 00:39:33 +00001842 void test() {
1843 lck_mtx_lock(&lck1);
1844 lck_mtx_lock(&lck2);
1845 lck_mtx_unlock(&lck1);
1846 // warn: this was not the most recently acquired lock
1847 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001848
Kristof Umann1a170322019-02-05 00:39:33 +00001849 lck_mtx_t lck1, lck2;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001850
Kristof Umann1a170322019-02-05 00:39:33 +00001851 void test() {
1852 if (lck_mtx_try_lock(&lck1) == 0)
1853 return;
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001854
Kristof Umann1a170322019-02-05 00:39:33 +00001855 lck_mtx_lock(&lck2);
1856 lck_mtx_unlock(&lck1);
1857 // warn: this was not the most recently acquired lock
1858 }
1859
1860alpha.unix.SimpleStream (C)
1861"""""""""""""""""""""""""""
1862Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fclose``
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001863(demo checker, the subject of the demo (`Slides <http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf>`_ ,
1864`Video <https://youtu.be/kdxlsP5QVPw>`_) by Anna Zaks and Jordan Rose presented at the
Kristof Umann1a170322019-02-05 00:39:33 +00001865`2012 LLVM Developers' Meeting <http://llvm.org/devmtg/2012-11/>`_).
1866
1867.. code-block:: c
1868
1869 void test() {
1870 FILE *F = fopen("myfile.txt", "w");
1871 } // warn: opened file is never closed
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001872
Kristof Umann1a170322019-02-05 00:39:33 +00001873 void test() {
1874 FILE *F = fopen("myfile.txt", "w");
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001875
Kristof Umann1a170322019-02-05 00:39:33 +00001876 if (F)
1877 fclose(F);
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001878
Kristof Umann1a170322019-02-05 00:39:33 +00001879 fclose(F); // warn: closing a previously closed file stream
1880 }
1881
1882alpha.unix.Stream (C)
1883"""""""""""""""""""""
1884Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,``
1885``fsetpos, clearerr, feof, ferror, fileno``.
1886
1887.. code-block:: c
1888
1889 void test() {
1890 FILE *p = fopen("foo", "r");
1891 } // warn: opened file is never closed
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001892
Kristof Umann1a170322019-02-05 00:39:33 +00001893 void test() {
1894 FILE *p = fopen("foo", "r");
1895 fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
1896 fclose(p);
1897 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001898
Kristof Umann1a170322019-02-05 00:39:33 +00001899 void test() {
1900 FILE *p = fopen("foo", "r");
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001901
Kristof Umann1a170322019-02-05 00:39:33 +00001902 if (p)
1903 fseek(p, 1, 3);
1904 // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001905
Kristof Umann1a170322019-02-05 00:39:33 +00001906 fclose(p);
1907 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001908
Kristof Umann1a170322019-02-05 00:39:33 +00001909 void test() {
1910 FILE *p = fopen("foo", "r");
1911 fclose(p);
1912 fclose(p); // warn: already closed
1913 }
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001914
Kristof Umann1a170322019-02-05 00:39:33 +00001915 void test() {
1916 FILE *p = tmpfile();
1917 ftell(p); // warn: stream pointer might be NULL
1918 fclose(p);
1919 }
1920
1921
1922alpha.unix.cstring.BufferOverlap (C)
1923""""""""""""""""""""""""""""""""""""
1924Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy``.
1925
1926.. code-block:: c
1927
1928 void test() {
1929 int a[4] = {0};
1930 memcpy(a + 2, a + 1, 8); // warn
1931 }
1932
1933alpha.unix.cstring.NotNullTerminated (C)
1934""""""""""""""""""""""""""""""""""""""""
1935Check for arguments which are not null-terminated strings; applies to: ``strlen, strnlen, strcpy, strncpy, strcat, strncat``.
1936
1937.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001938
Kristof Umann1a170322019-02-05 00:39:33 +00001939 void test() {
1940 int y = strlen((char *)&test); // warn
1941 }
1942
1943alpha.unix.cstring.OutOfBounds (C)
1944""""""""""""""""""""""""""""""""""
1945Check for out-of-bounds access in string functions; applies to:`` strncopy, strncat``.
1946
1947
1948.. code-block:: c
Alexander Kornienko9a857d22019-02-11 15:17:13 +00001949
Kristof Umann1a170322019-02-05 00:39:33 +00001950 void test() {
1951 int y = strlen((char *)&test); // warn
1952 }
1953
Mandeep Singh Grang0cdc5dd2019-05-24 19:24:08 +00001954alpha.nondeterminism.PointerIteration (C++)
1955"""""""""""""""""""""""""""""""""""""""""""
1956Check for non-determinism caused by iterating unordered containers of pointers.
1957
1958.. code-block:: c
1959
1960 void test() {
1961 int a = 1, b = 2;
1962 std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
1963
1964 for (auto i : UnorderedPtrSet) // warn
1965 f(i);
1966 }
1967
Mandeep Singh Grangc0773ab2019-03-08 20:13:53 +00001968alpha.nondeterminism.PointerSorting (C++)
Mandeep Singh Grangd4c4f742019-03-08 20:35:25 +00001969"""""""""""""""""""""""""""""""""""""""""
Mandeep Singh Grangc0773ab2019-03-08 20:13:53 +00001970Check for non-determinism caused by sorting of pointers.
1971
1972.. code-block:: c
1973
1974 void test() {
1975 int a = 1, b = 2;
1976 std::vector<int *> V = {&a, &b};
1977 std::sort(V.begin(), V.end()); // warn
1978 }
1979
Kristof Umann1a170322019-02-05 00:39:33 +00001980
1981Debug Checkers
1982---------------
1983
1984.. _debug-checkers:
1985
1986
1987debug
1988^^^^^
1989
1990Checkers used for debugging the analyzer.
Kristof Umanndccfaff2019-02-05 10:19:39 +00001991:doc:`developer-docs/DebugChecks` page contains a detailed description.
Kristof Umann1a170322019-02-05 00:39:33 +00001992
1993debug.AnalysisOrder
1994"""""""""""""""""""
1995Print callbacks that are called during analysis in order.
1996
1997debug.ConfigDumper
1998""""""""""""""""""
1999Dump config table.
2000
2001debug.DumpCFG Display
2002"""""""""""""""""""""
2003Control-Flow Graphs.
2004
2005debug.DumpCallGraph
2006"""""""""""""""""""
2007Display Call Graph.
2008
2009debug.DumpCalls
2010"""""""""""""""
2011Print calls as they are traversed by the engine.
2012
2013debug.DumpDominators
2014""""""""""""""""""""
2015Print the dominance tree for a given CFG.
2016
2017debug.DumpLiveVars
2018""""""""""""""""""
2019Print results of live variable analysis.
2020
2021debug.DumpTraversal
2022"""""""""""""""""""
2023Print branch conditions as they are traversed by the engine.
2024
2025debug.ExprInspection
2026""""""""""""""""""""
2027Check the analyzer's understanding of expressions.
2028
2029debug.Stats
2030"""""""""""
2031Emit warnings with analyzer statistics.
2032
2033debug.TaintTest
2034"""""""""""""""
2035Mark tainted symbols as such.
2036
2037debug.ViewCFG
2038"""""""""""""
2039View Control-Flow Graphs using GraphViz.
2040
2041debug.ViewCallGraph
2042"""""""""""""""""""
2043View Call Graph using GraphViz.
2044
2045debug.ViewExplodedGraph
2046"""""""""""""""""""""""
2047View Exploded Graphs using GraphViz.
2048