1================== 2Available Checkers 3================== 4 5The analyzer performs checks that are categorized into families or "checkers". 6 7The 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 10In 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^^^^ 28Models core language features and contains general-purpose checkers such as division by zero, 29null pointer dereference, usage of uninitialized values, etc. 30*These checkers must be always switched on as other checker rely on them.* 31 32.. _core-CallAndMessage: 33 34core.CallAndMessage (C, C++, ObjC) 35"""""""""""""""""""""""""""""""""" 36 Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers). 37 38.. literalinclude:: checkers/callandmessage_example.c 39 :language: objc 40 41.. _core-DivideZero: 42 43core.DivideZero (C, C++, ObjC) 44"""""""""""""""""""""""""""""" 45 Check for division by zero. 46 47.. literalinclude:: checkers/dividezero_example.c 48 :language: c 49 50.. _core-NonNullParamChecker: 51 52core.NonNullParamChecker (C, C++, ObjC) 53""""""""""""""""""""""""""""""""""""""" 54Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute. 55 56.. code-block:: cpp 57 58 int f(int *p) __attribute__((nonnull)); 59 60 void test(int *p) { 61 if (!p) 62 f(p); // warn 63 } 64 65.. _core-NullDereference: 66 67core.NullDereference (C, C++, ObjC) 68""""""""""""""""""""""""""""""""""" 69Check for dereferences of null pointers. 70 71.. code-block:: objc 72 73 // C 74 void test(int *p) { 75 if (p) 76 return; 77 78 int x = p[0]; // warn 79 } 80 81 // C 82 void test(int *p) { 83 if (!p) 84 *p = 0; // warn 85 } 86 87 // C++ 88 class C { 89 public: 90 int x; 91 }; 92 93 void test() { 94 C *pc = 0; 95 int k = pc->x; // warn 96 } 97 98 // Objective-C 99 @interface MyClass { 100 @public 101 int x; 102 } 103 @end 104 105 void test() { 106 MyClass *obj = 0; 107 obj->x = 1; // warn 108 } 109 110.. _core-StackAddressEscape: 111 112core.StackAddressEscape (C) 113""""""""""""""""""""""""""" 114Check that addresses to stack memory do not escape the function. 115 116.. code-block:: c 117 118 char const *p; 119 120 void test() { 121 char const str[] = "string"; 122 p = str; // warn 123 } 124 125 void* test() { 126 return __builtin_alloca(12); // warn 127 } 128 129 void test() { 130 static int *x; 131 int y; 132 x = &y; // warn 133 } 134 135 136.. _core-UndefinedBinaryOperatorResult: 137 138core.UndefinedBinaryOperatorResult (C) 139"""""""""""""""""""""""""""""""""""""" 140Check for undefined results of binary operators. 141 142.. code-block:: c 143 144 void test() { 145 int x; 146 int y = x + 1; // warn: left operand is garbage 147 } 148 149.. _core-VLASize: 150 151core.VLASize (C) 152"""""""""""""""" 153Check for declarations of Variable Length Arrays of undefined or zero size. 154 155 Check for declarations of VLA of undefined or zero size. 156 157.. code-block:: c 158 159 void test() { 160 int x; 161 int vla1[x]; // warn: garbage as size 162 } 163 164 void test() { 165 int x = 0; 166 int vla2[x]; // warn: zero size 167 } 168 169.. _core-uninitialized-ArraySubscript: 170 171core.uninitialized.ArraySubscript (C) 172""""""""""""""""""""""""""""""""""""" 173Check for uninitialized values used as array subscripts. 174 175.. code-block:: c 176 177 void test() { 178 int i, a[10]; 179 int x = a[i]; // warn: array subscript is undefined 180 } 181 182.. _core-uninitialized-Assign: 183 184core.uninitialized.Assign (C) 185""""""""""""""""""""""""""""" 186Check for assigning uninitialized values. 187 188.. code-block:: c 189 190 void test() { 191 int x; 192 x |= 1; // warn: left expression is uninitialized 193 } 194 195.. _core-uninitialized-Branch: 196 197core.uninitialized.Branch (C) 198""""""""""""""""""""""""""""" 199Check for uninitialized values used as branch conditions. 200 201.. code-block:: c 202 203 void test() { 204 int x; 205 if (x) // warn 206 return; 207 } 208 209.. _core-uninitialized-CapturedBlockVariable: 210 211core.uninitialized.CapturedBlockVariable (C) 212"""""""""""""""""""""""""""""""""""""""""""" 213Check for blocks that capture uninitialized values. 214 215.. code-block:: c 216 217 void test() { 218 int x; 219 ^{ int y = x; }(); // warn 220 } 221 222.. _core-uninitialized-UndefReturn: 223 224core.uninitialized.UndefReturn (C) 225"""""""""""""""""""""""""""""""""" 226Check for uninitialized values being returned to the caller. 227 228.. code-block:: c 229 230 int test() { 231 int x; 232 return x; // warn 233 } 234 235.. _cplusplus-checkers: 236 237 238cplusplus 239^^^^^^^^^ 240 241C++ Checkers. 242 243.. _cplusplus-InnerPointer: 244 245cplusplus.InnerPointer (C++) 246"""""""""""""""""""""""""""" 247Check for inner pointers of C++ containers used after re/deallocation. 248 249Many container methods in the C++ standard library are known to invalidate 250"references" (including actual references, iterators and raw pointers) to 251elements of the container. Using such references after they are invalidated 252causes undefined behavior, which is a common source of memory errors in C++ that 253this checker is capable of finding. 254 255The checker is currently limited to ``std::string`` objects and doesn't 256recognize some of the more sophisticated approaches to passing unowned pointers 257around, such as ``std::string_view``. 258 259.. code-block:: cpp 260 261 void deref_after_assignment() { 262 std::string s = "llvm"; 263 const char *c = s.data(); // note: pointer to inner buffer of 'std::string' obtained here 264 s = "clang"; // note: inner buffer of 'std::string' reallocated by call to 'operator=' 265 consume(c); // warn: inner pointer of container used after re/deallocation 266 } 267 268 const char *return_temp(int x) { 269 return std::to_string(x).c_str(); // warn: inner pointer of container used after re/deallocation 270 // note: pointer to inner buffer of 'std::string' obtained here 271 // note: inner buffer of 'std::string' deallocated by call to destructor 272 } 273 274.. _cplusplus-NewDelete: 275 276cplusplus.NewDelete (C++) 277""""""""""""""""""""""""" 278Check for double-free and use-after-free problems. Traces memory managed by new/delete. 279 280.. literalinclude:: checkers/newdelete_example.cpp 281 :language: cpp 282 283.. _cplusplus-NewDeleteLeaks: 284 285cplusplus.NewDeleteLeaks (C++) 286"""""""""""""""""""""""""""""" 287Check for memory leaks. Traces memory managed by new/delete. 288 289.. code-block:: cpp 290 291 void test() { 292 int *p = new int; 293 } // warn 294 295.. _cplusplus-PlacementNewChecker: 296 297cplusplus.PlacementNewChecker (C++) 298""""""""""""""""""""""""""""""""""" 299Check if default placement new is provided with pointers to sufficient storage capacity. 300 301.. code-block:: cpp 302 303 #include <new> 304 305 void f() { 306 short s; 307 long *lp = ::new (&s) long; // warn 308 } 309 310.. _cplusplus-SelfAssignment: 311 312cplusplus.SelfAssignment (C++) 313"""""""""""""""""""""""""""""" 314Checks C++ copy and move assignment operators for self assignment. 315 316.. _deadcode-checkers: 317 318deadcode 319^^^^^^^^ 320 321Dead Code Checkers. 322 323.. _deadcode-DeadStores: 324 325deadcode.DeadStores (C) 326""""""""""""""""""""""" 327Check for values stored to variables that are never read afterwards. 328 329.. code-block:: c 330 331 void test() { 332 int x; 333 x = 1; // warn 334 } 335 336The ``WarnForDeadNestedAssignments`` option enables the checker to emit 337warnings for nested dead assignments. You can disable with the 338``-analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false``. 339*Defaults to true*. 340 341Would warn for this e.g.: 342if ((y = make_int())) { 343} 344 345.. _nullability-checkers: 346 347nullability 348^^^^^^^^^^^ 349 350Objective C checkers that warn for null pointer passing and dereferencing errors. 351 352.. _nullability-NullPassedToNonnull: 353 354nullability.NullPassedToNonnull (ObjC) 355"""""""""""""""""""""""""""""""""""""" 356Warns when a null pointer is passed to a pointer which has a _Nonnull type. 357 358.. code-block:: objc 359 360 if (name != nil) 361 return; 362 // Warning: nil passed to a callee that requires a non-null 1st parameter 363 NSString *greeting = [@"Hello " stringByAppendingString:name]; 364 365.. _nullability-NullReturnedFromNonnull: 366 367nullability.NullReturnedFromNonnull (ObjC) 368"""""""""""""""""""""""""""""""""""""""""" 369Warns when a null pointer is returned from a function that has _Nonnull return type. 370 371.. code-block:: objc 372 373 - (nonnull id)firstChild { 374 id result = nil; 375 if ([_children count] > 0) 376 result = _children[0]; 377 378 // Warning: nil returned from a method that is expected 379 // to return a non-null value 380 return result; 381 } 382 383.. _nullability-NullableDereferenced: 384 385nullability.NullableDereferenced (ObjC) 386""""""""""""""""""""""""""""""""""""""" 387Warns when a nullable pointer is dereferenced. 388 389.. code-block:: objc 390 391 struct LinkedList { 392 int data; 393 struct LinkedList *next; 394 }; 395 396 struct LinkedList * _Nullable getNext(struct LinkedList *l); 397 398 void updateNextData(struct LinkedList *list, int newData) { 399 struct LinkedList *next = getNext(list); 400 // Warning: Nullable pointer is dereferenced 401 next->data = 7; 402 } 403 404.. _nullability-NullablePassedToNonnull: 405 406nullability.NullablePassedToNonnull (ObjC) 407"""""""""""""""""""""""""""""""""""""""""" 408Warns when a nullable pointer is passed to a pointer which has a _Nonnull type. 409 410.. code-block:: objc 411 412 typedef struct Dummy { int val; } Dummy; 413 Dummy *_Nullable returnsNullable(); 414 void takesNonnull(Dummy *_Nonnull); 415 416 void test() { 417 Dummy *p = returnsNullable(); 418 takesNonnull(p); // warn 419 } 420 421.. _nullability-NullableReturnedFromNonnull: 422 423nullability.NullableReturnedFromNonnull (ObjC) 424"""""""""""""""""""""""""""""""""""""""""""""" 425Warns when a nullable pointer is returned from a function that has _Nonnull return type. 426 427.. _optin-checkers: 428 429optin 430^^^^^ 431 432Checkers for portability, performance or coding style specific rules. 433 434.. _optin-cplusplus-UninitializedObject: 435 436optin.cplusplus.UninitializedObject (C++) 437""""""""""""""""""""""""""""""""""""""""" 438 439This checker reports uninitialized fields in objects created after a constructor 440call. It doesn't only find direct uninitialized fields, but rather makes a deep 441inspection of the object, analyzing all of its fields' subfields. 442The checker regards inherited fields as direct fields, so one will receive 443warnings for uninitialized inherited data members as well. 444 445.. code-block:: cpp 446 447 // With Pedantic and CheckPointeeInitialization set to true 448 449 struct A { 450 struct B { 451 int x; // note: uninitialized field 'this->b.x' 452 // note: uninitialized field 'this->bptr->x' 453 int y; // note: uninitialized field 'this->b.y' 454 // note: uninitialized field 'this->bptr->y' 455 }; 456 int *iptr; // note: uninitialized pointer 'this->iptr' 457 B b; 458 B *bptr; 459 char *cptr; // note: uninitialized pointee 'this->cptr' 460 461 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} 462 }; 463 464 void f() { 465 A::B b; 466 char c; 467 A a(&b, &c); // warning: 6 uninitialized fields 468 // after the constructor call 469 } 470 471 // With Pedantic set to false and 472 // CheckPointeeInitialization set to true 473 // (every field is uninitialized) 474 475 struct A { 476 struct B { 477 int x; 478 int y; 479 }; 480 int *iptr; 481 B b; 482 B *bptr; 483 char *cptr; 484 485 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} 486 }; 487 488 void f() { 489 A::B b; 490 char c; 491 A a(&b, &c); // no warning 492 } 493 494 // With Pedantic set to true and 495 // CheckPointeeInitialization set to false 496 // (pointees are regarded as initialized) 497 498 struct A { 499 struct B { 500 int x; // note: uninitialized field 'this->b.x' 501 int y; // note: uninitialized field 'this->b.y' 502 }; 503 int *iptr; // note: uninitialized pointer 'this->iptr' 504 B b; 505 B *bptr; 506 char *cptr; 507 508 A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} 509 }; 510 511 void f() { 512 A::B b; 513 char c; 514 A a(&b, &c); // warning: 3 uninitialized fields 515 // after the constructor call 516 } 517 518 519**Options** 520 521This checker has several options which can be set from command line (e.g. 522``-analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true``): 523 524* ``Pedantic`` (boolean). If to false, the checker won't emit warnings for 525 objects that don't have at least one initialized field. Defaults to false. 526 527* ``NotesAsWarnings`` (boolean). If set to true, the checker will emit a 528 warning for each uninitialized field, as opposed to emitting one warning per 529 constructor call, and listing the uninitialized fields that belongs to it in 530 notes. *Defaults to false*. 531 532* ``CheckPointeeInitialization`` (boolean). If set to false, the checker will 533 not analyze the pointee of pointer/reference fields, and will only check 534 whether the object itself is initialized. *Defaults to false*. 535 536* ``IgnoreRecordsWithField`` (string). If supplied, the checker will not analyze 537 structures that have a field with a name or type name that matches the given 538 pattern. *Defaults to ""*. 539 540.. _optin-cplusplus-VirtualCall: 541 542optin.cplusplus.VirtualCall (C++) 543""""""""""""""""""""""""""""""""" 544Check virtual function calls during construction or destruction. 545 546.. code-block:: cpp 547 548 class A { 549 public: 550 A() { 551 f(); // warn 552 } 553 virtual void f(); 554 }; 555 556 class A { 557 public: 558 ~A() { 559 this->f(); // warn 560 } 561 virtual void f(); 562 }; 563 564.. _optin-mpi-MPI-Checker: 565 566optin.mpi.MPI-Checker (C) 567""""""""""""""""""""""""" 568Checks MPI code. 569 570.. code-block:: c 571 572 void test() { 573 double buf = 0; 574 MPI_Request sendReq1; 575 MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 576 0, MPI_COMM_WORLD, &sendReq1); 577 } // warn: request 'sendReq1' has no matching wait. 578 579 void test() { 580 double buf = 0; 581 MPI_Request sendReq; 582 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); 583 MPI_Irecv(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn 584 MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // warn 585 MPI_Wait(&sendReq, MPI_STATUS_IGNORE); 586 } 587 588 void missingNonBlocking() { 589 int rank = 0; 590 MPI_Comm_rank(MPI_COMM_WORLD, &rank); 591 MPI_Request sendReq1[10][10][10]; 592 MPI_Wait(&sendReq1[1][7][9], MPI_STATUS_IGNORE); // warn 593 } 594 595.. _optin-osx-cocoa-localizability-EmptyLocalizationContextChecker: 596 597optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (ObjC) 598""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 599Check that NSLocalizedString macros include a comment for context. 600 601.. code-block:: objc 602 603 - (void)test { 604 NSString *string = NSLocalizedString(@"LocalizedString", nil); // warn 605 NSString *string2 = NSLocalizedString(@"LocalizedString", @" "); // warn 606 NSString *string3 = NSLocalizedStringWithDefaultValue( 607 @"LocalizedString", nil, [[NSBundle alloc] init], nil,@""); // warn 608 } 609 610.. _optin-osx-cocoa-localizability-NonLocalizedStringChecker: 611 612optin.osx.cocoa.localizability.NonLocalizedStringChecker (ObjC) 613""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 614Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings. 615 616.. code-block:: objc 617 618 NSString *alarmText = 619 NSLocalizedString(@"Enabled", @"Indicates alarm is turned on"); 620 if (!isEnabled) { 621 alarmText = @"Disabled"; 622 } 623 UILabel *alarmStateLabel = [[UILabel alloc] init]; 624 625 // Warning: User-facing text should use localized string macro 626 [alarmStateLabel setText:alarmText]; 627 628.. _optin-performance-GCDAntipattern: 629 630optin.performance.GCDAntipattern 631"""""""""""""""""""""""""""""""" 632Check for performance anti-patterns when using Grand Central Dispatch. 633 634.. _optin-performance-Padding: 635 636optin.performance.Padding 637""""""""""""""""""""""""" 638Check for excessively padded structs. 639 640.. _optin-portability-UnixAPI: 641 642optin.portability.UnixAPI 643""""""""""""""""""""""""" 644Finds implementation-defined behavior in UNIX/Posix functions. 645 646 647.. _security-checkers: 648 649security 650^^^^^^^^ 651 652Security related checkers. 653 654.. _security-FloatLoopCounter: 655 656security.FloatLoopCounter (C) 657""""""""""""""""""""""""""""" 658Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP). 659 660.. code-block:: c 661 662 void test() { 663 for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // warn 664 } 665 666.. _security-insecureAPI-UncheckedReturn: 667 668security.insecureAPI.UncheckedReturn (C) 669"""""""""""""""""""""""""""""""""""""""" 670Warn on uses of functions whose return values must be always checked. 671 672.. code-block:: c 673 674 void test() { 675 setuid(1); // warn 676 } 677 678.. _security-insecureAPI-bcmp: 679 680security.insecureAPI.bcmp (C) 681""""""""""""""""""""""""""""" 682Warn on uses of the 'bcmp' function. 683 684.. code-block:: c 685 686 void test() { 687 bcmp(ptr0, ptr1, n); // warn 688 } 689 690.. _security-insecureAPI-bcopy: 691 692security.insecureAPI.bcopy (C) 693"""""""""""""""""""""""""""""" 694Warn on uses of the 'bcopy' function. 695 696.. code-block:: c 697 698 void test() { 699 bcopy(src, dst, n); // warn 700 } 701 702.. _security-insecureAPI-bzero: 703 704security.insecureAPI.bzero (C) 705"""""""""""""""""""""""""""""" 706Warn on uses of the 'bzero' function. 707 708.. code-block:: c 709 710 void test() { 711 bzero(ptr, n); // warn 712 } 713 714.. _security-insecureAPI-getpw: 715 716security.insecureAPI.getpw (C) 717"""""""""""""""""""""""""""""" 718Warn on uses of the 'getpw' function. 719 720.. code-block:: c 721 722 void test() { 723 char buff[1024]; 724 getpw(2, buff); // warn 725 } 726 727.. _security-insecureAPI-gets: 728 729security.insecureAPI.gets (C) 730""""""""""""""""""""""""""""" 731Warn on uses of the 'gets' function. 732 733.. code-block:: c 734 735 void test() { 736 char buff[1024]; 737 gets(buff); // warn 738 } 739 740.. _security-insecureAPI-mkstemp: 741 742security.insecureAPI.mkstemp (C) 743"""""""""""""""""""""""""""""""" 744Warn when 'mkstemp' is passed fewer than 6 X's in the format string. 745 746.. code-block:: c 747 748 void test() { 749 mkstemp("XX"); // warn 750 } 751 752.. _security-insecureAPI-mktemp: 753 754security.insecureAPI.mktemp (C) 755""""""""""""""""""""""""""""""" 756Warn on uses of the ``mktemp`` function. 757 758.. code-block:: c 759 760 void test() { 761 char *x = mktemp("/tmp/zxcv"); // warn: insecure, use mkstemp 762 } 763 764.. _security-insecureAPI-rand: 765 766security.insecureAPI.rand (C) 767""""""""""""""""""""""""""""" 768Warn on uses of inferior random number generating functions (only if arc4random function is available): 769``drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, random, rand_r``. 770 771.. code-block:: c 772 773 void test() { 774 random(); // warn 775 } 776 777.. _security-insecureAPI-strcpy: 778 779security.insecureAPI.strcpy (C) 780""""""""""""""""""""""""""""""" 781Warn on uses of the ``strcpy`` and ``strcat`` functions. 782 783.. code-block:: c 784 785 void test() { 786 char x[4]; 787 char *y = "abcd"; 788 789 strcpy(x, y); // warn 790 } 791 792 793.. _security-insecureAPI-vfork: 794 795security.insecureAPI.vfork (C) 796"""""""""""""""""""""""""""""" 797 Warn on uses of the 'vfork' function. 798 799.. code-block:: c 800 801 void test() { 802 vfork(); // warn 803 } 804 805.. _security-insecureAPI-DeprecatedOrUnsafeBufferHandling: 806 807security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C) 808""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 809 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`` 810 811.. code-block:: c 812 813 void test() { 814 char buf [5]; 815 strncpy(buf, "a", 1); // warn 816 } 817 818.. _unix-checkers: 819 820unix 821^^^^ 822POSIX/Unix checkers. 823 824.. _unix-API: 825 826unix.API (C) 827"""""""""""" 828Check calls to various UNIX/Posix functions: ``open, pthread_once, calloc, malloc, realloc, alloca``. 829 830.. literalinclude:: checkers/unix_api_example.c 831 :language: c 832 833.. _unix-Malloc: 834 835unix.Malloc (C) 836""""""""""""""" 837Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free(). 838 839.. literalinclude:: checkers/unix_malloc_example.c 840 :language: c 841 842.. _unix-MallocSizeof: 843 844unix.MallocSizeof (C) 845""""""""""""""""""""" 846Check for dubious ``malloc`` arguments involving ``sizeof``. 847 848.. code-block:: c 849 850 void test() { 851 long *p = malloc(sizeof(short)); 852 // warn: result is converted to 'long *', which is 853 // incompatible with operand type 'short' 854 free(p); 855 } 856 857.. _unix-MismatchedDeallocator: 858 859unix.MismatchedDeallocator (C, C++) 860""""""""""""""""""""""""""""""""""" 861Check for mismatched deallocators. 862 863.. literalinclude:: checkers/mismatched_deallocator_example.cpp 864 :language: c 865 866.. _unix-Vfork: 867 868unix.Vfork (C) 869"""""""""""""" 870Check for proper usage of ``vfork``. 871 872.. code-block:: c 873 874 int test(int x) { 875 pid_t pid = vfork(); // warn 876 if (pid != 0) 877 return 0; 878 879 switch (x) { 880 case 0: 881 pid = 1; 882 execl("", "", 0); 883 _exit(1); 884 break; 885 case 1: 886 x = 0; // warn: this assignment is prohibited 887 break; 888 case 2: 889 foo(); // warn: this function call is prohibited 890 break; 891 default: 892 return 0; // warn: return is prohibited 893 } 894 895 while(1); 896 } 897 898.. _unix-cstring-BadSizeArg: 899 900unix.cstring.BadSizeArg (C) 901""""""""""""""""""""""""""" 902Check 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. 903 904.. code-block:: c 905 906 void test() { 907 char dest[3]; 908 strncat(dest, """""""""""""""""""""""""*", sizeof(dest)); 909 // warn: potential buffer overflow 910 } 911 912.. _unix-cstrisng-NullArg: 913 914unix.cstrisng.NullArg (C) 915""""""""""""""""""""""""" 916Check for null pointers being passed as arguments to C string functions: 917``strlen, strnlen, strcpy, strncpy, strcat, strncat, strcmp, strncmp, strcasecmp, strncasecmp``. 918 919.. code-block:: c 920 921 int test() { 922 return strlen(0); // warn 923 } 924 925.. _osx-checkers: 926 927osx 928^^^ 929macOS checkers. 930 931.. _osx-API: 932 933osx.API (C) 934""""""""""" 935Check for proper uses of various Apple APIs. 936 937.. code-block:: objc 938 939 void test() { 940 dispatch_once_t pred = 0; 941 dispatch_once(&pred, ^(){}); // warn: dispatch_once uses local 942 } 943 944.. _osx-NumberObjectConversion: 945 946osx.NumberObjectConversion (C, C++, ObjC) 947""""""""""""""""""""""""""""""""""""""""" 948Check for erroneous conversions of objects representing numbers into numbers. 949 950.. code-block:: objc 951 952 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"]; 953 // Warning: Comparing a pointer value of type 'NSNumber *' 954 // to a scalar integer value 955 if (photoCount > 0) { 956 [self displayPhotos]; 957 } 958 959.. _osx-ObjCProperty: 960 961osx.ObjCProperty (ObjC) 962""""""""""""""""""""""" 963Check for proper uses of Objective-C properties. 964 965.. code-block:: objc 966 967 NSNumber *photoCount = [albumDescriptor objectForKey:@"PhotoCount"]; 968 // Warning: Comparing a pointer value of type 'NSNumber *' 969 // to a scalar integer value 970 if (photoCount > 0) { 971 [self displayPhotos]; 972 } 973 974 975.. _osx-SecKeychainAPI: 976 977osx.SecKeychainAPI (C) 978"""""""""""""""""""""" 979Check for proper uses of Secure Keychain APIs. 980 981.. literalinclude:: checkers/seckeychainapi_example.m 982 :language: objc 983 984.. _osx-cocoa-AtSync: 985 986osx.cocoa.AtSync (ObjC) 987""""""""""""""""""""""" 988Check for nil pointers used as mutexes for @synchronized. 989 990.. code-block:: objc 991 992 void test(id x) { 993 if (!x) 994 @synchronized(x) {} // warn: nil value used as mutex 995 } 996 997 void test() { 998 id y; 999 @synchronized(y) {} // warn: uninitialized value used as mutex 1000 } 1001 1002.. _osx-cocoa-AutoreleaseWrite: 1003 1004osx.cocoa.AutoreleaseWrite 1005"""""""""""""""""""""""""" 1006Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C. 1007 1008.. _osx-cocoa-ClassRelease: 1009 1010osx.cocoa.ClassRelease (ObjC) 1011""""""""""""""""""""""""""""" 1012Check for sending 'retain', 'release', or 'autorelease' directly to a Class. 1013 1014.. code-block:: objc 1015 1016 @interface MyClass : NSObject 1017 @end 1018 1019 void test(void) { 1020 [MyClass release]; // warn 1021 } 1022 1023.. _osx-cocoa-Dealloc: 1024 1025osx.cocoa.Dealloc (ObjC) 1026"""""""""""""""""""""""" 1027Warn about Objective-C classes that lack a correct implementation of -dealloc 1028 1029.. literalinclude:: checkers/dealloc_example.m 1030 :language: objc 1031 1032.. _osx-cocoa-IncompatibleMethodTypes: 1033 1034osx.cocoa.IncompatibleMethodTypes (ObjC) 1035"""""""""""""""""""""""""""""""""""""""" 1036Warn about Objective-C method signatures with type incompatibilities. 1037 1038.. code-block:: objc 1039 1040 @interface MyClass1 : NSObject 1041 - (int)foo; 1042 @end 1043 1044 @implementation MyClass1 1045 - (int)foo { return 1; } 1046 @end 1047 1048 @interface MyClass2 : MyClass1 1049 - (float)foo; 1050 @end 1051 1052 @implementation MyClass2 1053 - (float)foo { return 1.0; } // warn 1054 @end 1055 1056.. _osx-cocoa-Loops: 1057 1058osx.cocoa.Loops 1059""""""""""""""" 1060Improved modeling of loops using Cocoa collection types. 1061 1062.. _osx-cocoa-MissingSuperCall: 1063 1064osx.cocoa.MissingSuperCall (ObjC) 1065""""""""""""""""""""""""""""""""" 1066Warn about Objective-C methods that lack a necessary call to super. 1067 1068.. code-block:: objc 1069 1070 @interface Test : UIViewController 1071 @end 1072 @implementation test 1073 - (void)viewDidLoad {} // warn 1074 @end 1075 1076 1077.. _osx-cocoa-NSAutoreleasePool: 1078 1079osx.cocoa.NSAutoreleasePool (ObjC) 1080"""""""""""""""""""""""""""""""""" 1081Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode. 1082 1083.. code-block:: objc 1084 1085 void test() { 1086 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 1087 [pool release]; // warn 1088 } 1089 1090.. _osx-cocoa-NSError: 1091 1092osx.cocoa.NSError (ObjC) 1093"""""""""""""""""""""""" 1094Check usage of NSError parameters. 1095 1096.. code-block:: objc 1097 1098 @interface A : NSObject 1099 - (void)foo:(NSError """""""""""""""""""""""")error; 1100 @end 1101 1102 @implementation A 1103 - (void)foo:(NSError """""""""""""""""""""""")error { 1104 // warn: method accepting NSError"""""""""""""""""""""""" should have a non-void 1105 // return value 1106 } 1107 @end 1108 1109 @interface A : NSObject 1110 - (BOOL)foo:(NSError """""""""""""""""""""""")error; 1111 @end 1112 1113 @implementation A 1114 - (BOOL)foo:(NSError """""""""""""""""""""""")error { 1115 *error = 0; // warn: potential null dereference 1116 return 0; 1117 } 1118 @end 1119 1120.. _osx-cocoa-NilArg: 1121 1122osx.cocoa.NilArg (ObjC) 1123""""""""""""""""""""""" 1124Check for prohibited nil arguments to ObjC method calls. 1125 1126 - caseInsensitiveCompare: 1127 - compare: 1128 - compare:options: 1129 - compare:options:range: 1130 - compare:options:range:locale: 1131 - componentsSeparatedByCharactersInSet: 1132 - initWithFormat: 1133 1134.. code-block:: objc 1135 1136 NSComparisonResult test(NSString *s) { 1137 NSString *aString = nil; 1138 return [s caseInsensitiveCompare:aString]; 1139 // warn: argument to 'NSString' method 1140 // 'caseInsensitiveCompare:' cannot be nil 1141 } 1142 1143 1144.. _osx-cocoa-NonNilReturnValue: 1145 1146osx.cocoa.NonNilReturnValue 1147""""""""""""""""""""""""""" 1148Models the APIs that are guaranteed to return a non-nil value. 1149 1150.. _osx-cocoa-ObjCGenerics: 1151 1152osx.cocoa.ObjCGenerics (ObjC) 1153""""""""""""""""""""""""""""" 1154Check for type errors when using Objective-C generics. 1155 1156.. code-block:: objc 1157 1158 NSMutableArray *names = [NSMutableArray array]; 1159 NSMutableArray *birthDates = names; 1160 1161 // Warning: Conversion from value of type 'NSDate *' 1162 // to incompatible type 'NSString *' 1163 [birthDates addObject: [NSDate date]]; 1164 1165.. _osx-cocoa-RetainCount: 1166 1167osx.cocoa.RetainCount (ObjC) 1168"""""""""""""""""""""""""""" 1169Check for leaks and improper reference count management 1170 1171.. code-block:: objc 1172 1173 void test() { 1174 NSString *s = [[NSString alloc] init]; // warn 1175 } 1176 1177 CFStringRef test(char *bytes) { 1178 return CFStringCreateWithCStringNoCopy( 1179 0, bytes, NSNEXTSTEPStringEncoding, 0); // warn 1180 } 1181 1182 1183.. _osx-cocoa-RunLoopAutoreleaseLeak: 1184 1185osx.cocoa.RunLoopAutoreleaseLeak 1186"""""""""""""""""""""""""""""""" 1187Check for leaked memory in autorelease pools that will never be drained. 1188 1189.. _osx-cocoa-SelfInit: 1190 1191osx.cocoa.SelfInit (ObjC) 1192""""""""""""""""""""""""" 1193Check that 'self' is properly initialized inside an initializer method. 1194 1195.. code-block:: objc 1196 1197 @interface MyObj : NSObject { 1198 id x; 1199 } 1200 - (id)init; 1201 @end 1202 1203 @implementation MyObj 1204 - (id)init { 1205 [super init]; 1206 x = 0; // warn: instance variable used while 'self' is not 1207 // initialized 1208 return 0; 1209 } 1210 @end 1211 1212 @interface MyObj : NSObject 1213 - (id)init; 1214 @end 1215 1216 @implementation MyObj 1217 - (id)init { 1218 [super init]; 1219 return self; // warn: returning uninitialized 'self' 1220 } 1221 @end 1222 1223.. _osx-cocoa-SuperDealloc: 1224 1225osx.cocoa.SuperDealloc (ObjC) 1226""""""""""""""""""""""""""""" 1227Warn about improper use of '[super dealloc]' in Objective-C. 1228 1229.. code-block:: objc 1230 1231 @interface SuperDeallocThenReleaseIvarClass : NSObject { 1232 NSObject *_ivar; 1233 } 1234 @end 1235 1236 @implementation SuperDeallocThenReleaseIvarClass 1237 - (void)dealloc { 1238 [super dealloc]; 1239 [_ivar release]; // warn 1240 } 1241 @end 1242 1243.. _osx-cocoa-UnusedIvars: 1244 1245osx.cocoa.UnusedIvars (ObjC) 1246"""""""""""""""""""""""""""" 1247Warn about private ivars that are never used. 1248 1249.. code-block:: objc 1250 1251 @interface MyObj : NSObject { 1252 @private 1253 id x; // warn 1254 } 1255 @end 1256 1257 @implementation MyObj 1258 @end 1259 1260.. _osx-cocoa-VariadicMethodTypes: 1261 1262osx.cocoa.VariadicMethodTypes (ObjC) 1263"""""""""""""""""""""""""""""""""""" 1264Check for passing non-Objective-C types to variadic collection 1265initialization methods that expect only Objective-C types. 1266 1267.. code-block:: objc 1268 1269 void test() { 1270 [NSSet setWithObjects:@"Foo", "Bar", nil]; 1271 // warn: argument should be an ObjC pointer type, not 'char *' 1272 } 1273 1274.. _osx-coreFoundation-CFError: 1275 1276osx.coreFoundation.CFError (C) 1277"""""""""""""""""""""""""""""" 1278Check usage of CFErrorRef* parameters 1279 1280.. code-block:: c 1281 1282 void test(CFErrorRef *error) { 1283 // warn: function accepting CFErrorRef* should have a 1284 // non-void return 1285 } 1286 1287 int foo(CFErrorRef *error) { 1288 *error = 0; // warn: potential null dereference 1289 return 0; 1290 } 1291 1292.. _osx-coreFoundation-CFNumber: 1293 1294osx.coreFoundation.CFNumber (C) 1295""""""""""""""""""""""""""""""" 1296Check for proper uses of CFNumber APIs. 1297 1298.. code-block:: c 1299 1300 CFNumberRef test(unsigned char x) { 1301 return CFNumberCreate(0, kCFNumberSInt16Type, &x); 1302 // warn: 8 bit integer is used to initialize a 16 bit integer 1303 } 1304 1305.. _osx-coreFoundation-CFRetainRelease: 1306 1307osx.coreFoundation.CFRetainRelease (C) 1308"""""""""""""""""""""""""""""""""""""" 1309Check for null arguments to CFRetain/CFRelease/CFMakeCollectable. 1310 1311.. code-block:: c 1312 1313 void test(CFTypeRef p) { 1314 if (!p) 1315 CFRetain(p); // warn 1316 } 1317 1318 void test(int x, CFTypeRef p) { 1319 if (p) 1320 return; 1321 1322 CFRelease(p); // warn 1323 } 1324 1325.. _osx-coreFoundation-containers-OutOfBounds: 1326 1327osx.coreFoundation.containers.OutOfBounds (C) 1328""""""""""""""""""""""""""""""""""""""""""""" 1329Checks for index out-of-bounds when using 'CFArray' API. 1330 1331.. code-block:: c 1332 1333 void test() { 1334 CFArrayRef A = CFArrayCreate(0, 0, 0, &kCFTypeArrayCallBacks); 1335 CFArrayGetValueAtIndex(A, 0); // warn 1336 } 1337 1338.. _osx-coreFoundation-containers-PointerSizedValues: 1339 1340osx.coreFoundation.containers.PointerSizedValues (C) 1341"""""""""""""""""""""""""""""""""""""""""""""""""""" 1342Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values. 1343 1344.. code-block:: c 1345 1346 void test() { 1347 int x[] = { 1 }; 1348 CFArrayRef A = CFArrayCreate(0, (const void """""""""""""""""""""""")x, 1, 1349 &kCFTypeArrayCallBacks); // warn 1350 } 1351 1352Fuchsia 1353^^^^^^^ 1354 1355Fuchsia is an open source capability-based operating system currently being 1356developed by Google. This section describes checkers that can find various 1357misuses of Fuchsia APIs. 1358 1359.. _fuchsia-HandleChecker: 1360 1361fuchsia.HandleChecker 1362"""""""""""""""""""""""""""" 1363Handles identify resources. Similar to pointers they can be leaked, 1364double freed, or use after freed. This check attempts to find such problems. 1365 1366.. code-block:: cpp 1367 1368 void checkLeak08(int tag) { 1369 zx_handle_t sa, sb; 1370 zx_channel_create(0, &sa, &sb); 1371 if (tag) 1372 zx_handle_close(sa); 1373 use(sb); // Warn: Potential leak of handle 1374 zx_handle_close(sb); 1375 } 1376 1377WebKit 1378^^^^^^ 1379 1380WebKit is an open-source web browser engine available for macOS, iOS and Linux. 1381This section describes checkers that can find issues in WebKit codebase. 1382 1383Most of the checkers focus on memory management for which WebKit uses custom implementation of reference counted smartpointers. 1384 1385Checkers are formulated in terms related to ref-counting: 1386 - *Ref-counted type* is either ``Ref<T>`` or ``RefPtr<T>``. 1387 - *Ref-countable type* is any type that implements ``ref()`` and ``deref()`` methods as ``RefPtr<>`` is a template (i. e. relies on duck typing). 1388 - *Uncounted type* is ref-countable but not ref-counted type. 1389 1390.. _webkit-RefCntblBaseVirtualDtor: 1391 1392webkit.RefCntblBaseVirtualDtor 1393"""""""""""""""""""""""""""""""""""" 1394All uncounted types used as base classes must have a virtual destructor. 1395 1396Ref-counted types hold their ref-countable data by a raw pointer and allow implicit upcasting from ref-counted pointer to derived type to ref-counted pointer to base type. This might lead to an object of (dynamic) derived type being deleted via pointer to the base class type which C++ standard defines as UB in case the base class doesn't have virtual destructor ``[expr.delete]``. 1397 1398.. code-block:: cpp 1399 1400 struct RefCntblBase { 1401 void ref() {} 1402 void deref() {} 1403 }; 1404 1405 struct Derived : RefCntblBase { }; // warn 1406 1407.. _webkit-NoUncountedMemberChecker: 1408 1409webkit.NoUncountedMemberChecker 1410""""""""""""""""""""""""""""""""""""" 1411Raw pointers and references to uncounted types can't be used as class members. Only ref-counted types are allowed. 1412 1413.. code-block:: cpp 1414 1415 struct RefCntbl { 1416 void ref() {} 1417 void deref() {} 1418 }; 1419 1420 struct Foo { 1421 RefCntbl * ptr; // warn 1422 RefCntbl & ptr; // warn 1423 // ... 1424 }; 1425 1426.. _webkit-UncountedLambdaCapturesChecker: 1427 1428webkit.UncountedLambdaCapturesChecker 1429""""""""""""""""""""""""""""""""""""" 1430Raw pointers and references to uncounted types can't be captured in lambdas. Only ref-counted types are allowed. 1431 1432.. code-block:: cpp 1433 1434 struct RefCntbl { 1435 void ref() {} 1436 void deref() {} 1437 }; 1438 1439 void foo(RefCntbl* a, RefCntbl& b) { 1440 [&, a](){ // warn about 'a' 1441 do_something(b); // warn about 'b' 1442 }; 1443 }; 1444 1445.. _alpha-checkers: 1446 1447Experimental Checkers 1448--------------------- 1449 1450*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.* 1451 1452alpha.clone 1453^^^^^^^^^^^ 1454 1455.. _alpha-clone-CloneChecker: 1456 1457alpha.clone.CloneChecker (C, C++, ObjC) 1458""""""""""""""""""""""""""""""""""""""" 1459Reports similar pieces of code. 1460 1461.. code-block:: c 1462 1463 void log(); 1464 1465 int max(int a, int b) { // warn 1466 log(); 1467 if (a > b) 1468 return a; 1469 return b; 1470 } 1471 1472 int maxClone(int x, int y) { // similar code here 1473 log(); 1474 if (x > y) 1475 return x; 1476 return y; 1477 } 1478 1479alpha.core 1480^^^^^^^^^^ 1481 1482.. _alpha-core-BoolAssignment: 1483 1484alpha.core.BoolAssignment (ObjC) 1485"""""""""""""""""""""""""""""""" 1486Warn about assigning non-{0,1} values to boolean variables. 1487 1488.. code-block:: objc 1489 1490 void test() { 1491 BOOL b = -1; // warn 1492 } 1493 1494.. _alpha-core-C11Lock: 1495 1496alpha.core.C11Lock 1497"""""""""""""""""" 1498Similarly to :ref:`alpha.unix.PthreadLock <alpha-unix-PthreadLock>`, checks for 1499the locking/unlocking of ``mtx_t`` mutexes. 1500 1501.. code-block:: cpp 1502 1503 mtx_t mtx1; 1504 1505 void bad1(void) 1506 { 1507 mtx_lock(&mtx1); 1508 mtx_lock(&mtx1); // warn: This lock has already been acquired 1509 } 1510 1511.. _alpha-core-CallAndMessageUnInitRefArg: 1512 1513alpha.core.CallAndMessageUnInitRefArg (C,C++, ObjC) 1514""""""""""""""""""""""""""""""""""""""""""""""""""" 1515Check for logical errors for function calls and Objective-C 1516message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables). 1517 1518.. code-block:: c 1519 1520 void test(void) { 1521 int t; 1522 int &p = t; 1523 int &s = p; 1524 int &q = s; 1525 foo(q); // warn 1526 } 1527 1528 void test(void) { 1529 int x; 1530 foo(&x); // warn 1531 } 1532 1533.. _alpha-core-CastSize: 1534 1535alpha.core.CastSize (C) 1536""""""""""""""""""""""" 1537Check when casting a malloc'ed type ``T``, whether the size is a multiple of the size of ``T``. 1538 1539.. code-block:: c 1540 1541 void test() { 1542 int *x = (int *) malloc(11); // warn 1543 } 1544 1545.. _alpha-core-CastToStruct: 1546 1547alpha.core.CastToStruct (C, C++) 1548"""""""""""""""""""""""""""""""" 1549Check for cast from non-struct pointer to struct pointer. 1550 1551.. code-block:: cpp 1552 1553 // C 1554 struct s {}; 1555 1556 void test(int *p) { 1557 struct s *ps = (struct s *) p; // warn 1558 } 1559 1560 // C++ 1561 class c {}; 1562 1563 void test(int *p) { 1564 c *pc = (c *) p; // warn 1565 } 1566 1567.. _alpha-core-Conversion: 1568 1569alpha.core.Conversion (C, C++, ObjC) 1570"""""""""""""""""""""""""""""""""""" 1571Loss of sign/precision in implicit conversions. 1572 1573.. code-block:: c 1574 1575 void test(unsigned U, signed S) { 1576 if (S > 10) { 1577 if (U < S) { 1578 } 1579 } 1580 if (S < -10) { 1581 if (U < S) { // warn (loss of sign) 1582 } 1583 } 1584 } 1585 1586 void test() { 1587 long long A = 1LL << 60; 1588 short X = A; // warn (loss of precision) 1589 } 1590 1591.. _alpha-core-DynamicTypeChecker: 1592 1593alpha.core.DynamicTypeChecker (ObjC) 1594"""""""""""""""""""""""""""""""""""" 1595Check for cases where the dynamic and the static type of an object are unrelated. 1596 1597 1598.. code-block:: objc 1599 1600 id date = [NSDate date]; 1601 1602 // Warning: Object has a dynamic type 'NSDate *' which is 1603 // incompatible with static type 'NSNumber *'" 1604 NSNumber *number = date; 1605 [number doubleValue]; 1606 1607.. _alpha-core-FixedAddr: 1608 1609alpha.core.FixedAddr (C) 1610"""""""""""""""""""""""" 1611Check for assignment of a fixed address to a pointer. 1612 1613.. code-block:: c 1614 1615 void test() { 1616 int *p; 1617 p = (int *) 0x10000; // warn 1618 } 1619 1620.. _alpha-core-IdenticalExpr: 1621 1622alpha.core.IdenticalExpr (C, C++) 1623""""""""""""""""""""""""""""""""" 1624Warn about unintended use of identical expressions in operators. 1625 1626.. code-block:: cpp 1627 1628 // C 1629 void test() { 1630 int a = 5; 1631 int b = a | 4 | a; // warn: identical expr on both sides 1632 } 1633 1634 // C++ 1635 bool f(void); 1636 1637 void test(bool b) { 1638 int i = 10; 1639 if (f()) { // warn: true and false branches are identical 1640 do { 1641 i--; 1642 } while (f()); 1643 } else { 1644 do { 1645 i--; 1646 } while (f()); 1647 } 1648 } 1649 1650.. _alpha-core-PointerArithm: 1651 1652alpha.core.PointerArithm (C) 1653"""""""""""""""""""""""""""" 1654Check for pointer arithmetic on locations other than array elements. 1655 1656.. code-block:: c 1657 1658 void test() { 1659 int x; 1660 int *p; 1661 p = &x + 1; // warn 1662 } 1663 1664.. _alpha-core-PointerSub: 1665 1666alpha.core.PointerSub (C) 1667""""""""""""""""""""""""" 1668Check for pointer subtractions on two pointers pointing to different memory chunks. 1669 1670.. code-block:: c 1671 1672 void test() { 1673 int x, y; 1674 int d = &y - &x; // warn 1675 } 1676 1677.. _alpha-core-SizeofPtr: 1678 1679alpha.core.SizeofPtr (C) 1680"""""""""""""""""""""""" 1681Warn about unintended use of ``sizeof()`` on pointer expressions. 1682 1683.. code-block:: c 1684 1685 struct s {}; 1686 1687 int test(struct s *p) { 1688 return sizeof(p); 1689 // warn: sizeof(ptr) can produce an unexpected result 1690 } 1691 1692.. _alpha-core-StackAddressAsyncEscape: 1693 1694alpha.core.StackAddressAsyncEscape (C) 1695"""""""""""""""""""""""""""""""""""""" 1696Check that addresses to stack memory do not escape the function that involves dispatch_after or dispatch_async. 1697This checker is a part of ``core.StackAddressEscape``, but is temporarily disabled until some false positives are fixed. 1698 1699.. code-block:: c 1700 1701 dispatch_block_t test_block_inside_block_async_leak() { 1702 int x = 123; 1703 void (^inner)(void) = ^void(void) { 1704 int y = x; 1705 ++y; 1706 }; 1707 void (^outer)(void) = ^void(void) { 1708 int z = x; 1709 ++z; 1710 inner(); 1711 }; 1712 return outer; // warn: address of stack-allocated block is captured by a 1713 // returned block 1714 } 1715 1716.. _alpha-core-TestAfterDivZero: 1717 1718alpha.core.TestAfterDivZero (C) 1719""""""""""""""""""""""""""""""" 1720Check for division by variable that is later compared against 0. 1721Either the comparison is useless or there is division by zero. 1722 1723.. code-block:: c 1724 1725 void test(int x) { 1726 var = 77 / x; 1727 if (x == 0) { } // warn 1728 } 1729 1730alpha.cplusplus 1731^^^^^^^^^^^^^^^ 1732 1733.. _alpha-cplusplus-DeleteWithNonVirtualDtor: 1734 1735alpha.cplusplus.DeleteWithNonVirtualDtor (C++) 1736"""""""""""""""""""""""""""""""""""""""""""""" 1737Reports destructions of polymorphic objects with a non-virtual destructor in their base class. 1738 1739.. code-block:: cpp 1740 1741 NonVirtual *create() { 1742 NonVirtual *x = new NVDerived(); // note: conversion from derived to base 1743 // happened here 1744 return x; 1745 } 1746 1747 void sink(NonVirtual *x) { 1748 delete x; // warn: destruction of a polymorphic object with no virtual 1749 // destructor 1750 } 1751 1752.. _alpha-cplusplus-EnumCastOutOfRange: 1753 1754alpha.cplusplus.EnumCastOutOfRange (C++) 1755"""""""""""""""""""""""""""""""""""""""" 1756Check for integer to enumeration casts that could result in undefined values. 1757 1758.. code-block:: cpp 1759 1760 enum TestEnum { 1761 A = 0 1762 }; 1763 1764 void foo() { 1765 TestEnum t = static_cast(-1); 1766 // warn: the value provided to the cast expression is not in 1767 // the valid range of values for the enum 1768 1769.. _alpha-cplusplus-InvalidatedIterator: 1770 1771alpha.cplusplus.InvalidatedIterator (C++) 1772""""""""""""""""""""""""""""""""""""""""" 1773Check for use of invalidated iterators. 1774 1775.. code-block:: cpp 1776 1777 void bad_copy_assign_operator_list1(std::list &L1, 1778 const std::list &L2) { 1779 auto i0 = L1.cbegin(); 1780 L1 = L2; 1781 *i0; // warn: invalidated iterator accessed 1782 } 1783 1784 1785.. _alpha-cplusplus-IteratorRange: 1786 1787alpha.cplusplus.IteratorRange (C++) 1788""""""""""""""""""""""""""""""""""" 1789Check for iterators used outside their valid ranges. 1790 1791.. code-block:: cpp 1792 1793 void simple_bad_end(const std::vector &v) { 1794 auto i = v.end(); 1795 *i; // warn: iterator accessed outside of its range 1796 } 1797 1798.. _alpha-cplusplus-MismatchedIterator: 1799 1800alpha.cplusplus.MismatchedIterator (C++) 1801"""""""""""""""""""""""""""""""""""""""" 1802Check for use of iterators of different containers where iterators of the same container are expected. 1803 1804.. code-block:: cpp 1805 1806 void bad_insert3(std::vector &v1, std::vector &v2) { 1807 v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed 1808 // using foreign 1809 // iterator argument 1810 v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of 1811 // different containers 1812 // used where the same 1813 // container is 1814 // expected 1815 v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of 1816 // different containers 1817 // used where the same 1818 // container is 1819 // expected 1820 } 1821 1822.. _alpha-cplusplus-MisusedMovedObject: 1823 1824alpha.cplusplus.MisusedMovedObject (C++) 1825"""""""""""""""""""""""""""""""""""""""" 1826Method calls on a moved-from object and copying a moved-from object will be reported. 1827 1828 1829.. code-block:: cpp 1830 1831 struct A { 1832 void foo() {} 1833 }; 1834 1835 void f() { 1836 A a; 1837 A b = std::move(a); // note: 'a' became 'moved-from' here 1838 a.foo(); // warn: method call on a 'moved-from' object 'a' 1839 } 1840 1841alpha.deadcode 1842^^^^^^^^^^^^^^ 1843.. _alpha-deadcode-UnreachableCode: 1844 1845alpha.deadcode.UnreachableCode (C, C++) 1846""""""""""""""""""""""""""""""""""""""" 1847Check unreachable code. 1848 1849.. code-block:: cpp 1850 1851 // C 1852 int test() { 1853 int x = 1; 1854 while(x); 1855 return x; // warn 1856 } 1857 1858 // C++ 1859 void test() { 1860 int a = 2; 1861 1862 while (a > 1) 1863 a--; 1864 1865 if (a > 1) 1866 a++; // warn 1867 } 1868 1869 // Objective-C 1870 void test(id x) { 1871 return; 1872 [x retain]; // warn 1873 } 1874 1875.. _alpha-cplusplus-SmartPtr: 1876 1877alpha.cplusplus.SmartPtr (C++) 1878"""""""""""""""""""""""""""""" 1879Check for dereference of null smart pointers. 1880 1881.. code-block:: cpp 1882 1883 void deref_smart_ptr() { 1884 std::unique_ptr<int> P; 1885 *P; // warn: dereference of a default constructed smart unique_ptr 1886 } 1887 1888alpha.fuchsia 1889^^^^^^^^^^^^^ 1890 1891.. _alpha-fuchsia-lock: 1892 1893alpha.fuchsia.Lock 1894"""""""""""""""""" 1895Similarly to :ref:`alpha.unix.PthreadLock <alpha-unix-PthreadLock>`, checks for 1896the locking/unlocking of fuchsia mutexes. 1897 1898.. code-block:: cpp 1899 1900 spin_lock_t mtx1; 1901 1902 void bad1(void) 1903 { 1904 spin_lock(&mtx1); 1905 spin_lock(&mtx1); // warn: This lock has already been acquired 1906 } 1907 1908alpha.llvm 1909^^^^^^^^^^ 1910 1911.. _alpha-llvm-Conventions: 1912 1913alpha.llvm.Conventions 1914"""""""""""""""""""""" 1915 1916Check code for LLVM codebase conventions: 1917 1918* A StringRef should not be bound to a temporary std::string whose lifetime is shorter than the StringRef's. 1919* Clang AST nodes should not have fields that can allocate memory. 1920 1921 1922alpha.osx 1923^^^^^^^^^ 1924 1925.. _alpha-osx-cocoa-DirectIvarAssignment: 1926 1927alpha.osx.cocoa.DirectIvarAssignment (ObjC) 1928""""""""""""""""""""""""""""""""""""""""""" 1929Check for direct assignments to instance variables. 1930 1931 1932.. code-block:: objc 1933 1934 @interface MyClass : NSObject {} 1935 @property (readonly) id A; 1936 - (void) foo; 1937 @end 1938 1939 @implementation MyClass 1940 - (void) foo { 1941 _A = 0; // warn 1942 } 1943 @end 1944 1945.. _alpha-osx-cocoa-DirectIvarAssignmentForAnnotatedFunctions: 1946 1947alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions (ObjC) 1948"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1949Check for direct assignments to instance variables in 1950the methods annotated with ``objc_no_direct_instance_variable_assignment``. 1951 1952.. code-block:: objc 1953 1954 @interface MyClass : NSObject {} 1955 @property (readonly) id A; 1956 - (void) fAnnotated __attribute__(( 1957 annotate("objc_no_direct_instance_variable_assignment"))); 1958 - (void) fNotAnnotated; 1959 @end 1960 1961 @implementation MyClass 1962 - (void) fAnnotated { 1963 _A = 0; // warn 1964 } 1965 - (void) fNotAnnotated { 1966 _A = 0; // no warn 1967 } 1968 @end 1969 1970 1971.. _alpha-osx-cocoa-InstanceVariableInvalidation: 1972 1973alpha.osx.cocoa.InstanceVariableInvalidation (ObjC) 1974""""""""""""""""""""""""""""""""""""""""""""""""""" 1975Check that the invalidatable instance variables are 1976invalidated in the methods annotated with objc_instance_variable_invalidator. 1977 1978.. code-block:: objc 1979 1980 @protocol Invalidation <NSObject> 1981 - (void) invalidate 1982 __attribute__((annotate("objc_instance_variable_invalidator"))); 1983 @end 1984 1985 @interface InvalidationImpObj : NSObject <Invalidation> 1986 @end 1987 1988 @interface SubclassInvalidationImpObj : InvalidationImpObj { 1989 InvalidationImpObj *var; 1990 } 1991 - (void)invalidate; 1992 @end 1993 1994 @implementation SubclassInvalidationImpObj 1995 - (void) invalidate {} 1996 @end 1997 // warn: var needs to be invalidated or set to nil 1998 1999.. _alpha-osx-cocoa-MissingInvalidationMethod: 2000 2001alpha.osx.cocoa.MissingInvalidationMethod (ObjC) 2002"""""""""""""""""""""""""""""""""""""""""""""""" 2003Check that the invalidation methods are present in classes that contain invalidatable instance variables. 2004 2005.. code-block:: objc 2006 2007 @protocol Invalidation <NSObject> 2008 - (void)invalidate 2009 __attribute__((annotate("objc_instance_variable_invalidator"))); 2010 @end 2011 2012 @interface NeedInvalidation : NSObject <Invalidation> 2013 @end 2014 2015 @interface MissingInvalidationMethodDecl : NSObject { 2016 NeedInvalidation *Var; // warn 2017 } 2018 @end 2019 2020 @implementation MissingInvalidationMethodDecl 2021 @end 2022 2023.. _alpha-osx-cocoa-localizability-PluralMisuseChecker: 2024 2025alpha.osx.cocoa.localizability.PluralMisuseChecker (ObjC) 2026""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2027Warns against using one vs. many plural pattern in code when generating localized strings. 2028 2029.. code-block:: objc 2030 2031 NSString *reminderText = 2032 NSLocalizedString(@"None", @"Indicates no reminders"); 2033 if (reminderCount == 1) { 2034 // Warning: Plural cases are not supported across all languages. 2035 // Use a .stringsdict file instead 2036 reminderText = 2037 NSLocalizedString(@"1 Reminder", @"Indicates single reminder"); 2038 } else if (reminderCount >= 2) { 2039 // Warning: Plural cases are not supported across all languages. 2040 // Use a .stringsdict file instead 2041 reminderText = 2042 [NSString stringWithFormat: 2043 NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"), 2044 reminderCount]; 2045 } 2046 2047alpha.security 2048^^^^^^^^^^^^^^ 2049 2050 2051alpha.security.cert 2052^^^^^^^^^^^^^^^^^^^ 2053 2054SEI CERT checkers which tries to find errors based on their `C coding rules <https://wiki.sei.cmu.edu/confluence/display/c/2+Rules>`_. 2055 2056.. _alpha-security-cert-pos-checkers: 2057 2058alpha.security.cert.pos 2059^^^^^^^^^^^^^^^^^^^^^^^ 2060 2061SEI CERT checkers of `POSIX C coding rules <https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152405>`_. 2062 2063.. _alpha-security-cert-pos-34c: 2064 2065alpha.security.cert.pos.34c 2066""""""""""""""""""""""""""" 2067Finds calls to the ``putenv`` function which pass a pointer to an automatic variable as the argument. 2068 2069.. code-block:: c 2070 2071 int func(const char *var) { 2072 char env[1024]; 2073 int retval = snprintf(env, sizeof(env),"TEST=%s", var); 2074 if (retval < 0 || (size_t)retval >= sizeof(env)) { 2075 /* Handle error */ 2076 } 2077 2078 return putenv(env); // putenv function should not be called with auto variables 2079 } 2080 2081.. _alpha-security-ArrayBound: 2082 2083alpha.security.ArrayBound (C) 2084""""""""""""""""""""""""""""" 2085Warn about buffer overflows (older checker). 2086 2087.. code-block:: c 2088 2089 void test() { 2090 char *s = ""; 2091 char c = s[1]; // warn 2092 } 2093 2094 struct seven_words { 2095 int c[7]; 2096 }; 2097 2098 void test() { 2099 struct seven_words a, *p; 2100 p = &a; 2101 p[0] = a; 2102 p[1] = a; 2103 p[2] = a; // warn 2104 } 2105 2106 // note: requires unix.Malloc or 2107 // alpha.unix.MallocWithAnnotations checks enabled. 2108 void test() { 2109 int *p = malloc(12); 2110 p[3] = 4; // warn 2111 } 2112 2113 void test() { 2114 char a[2]; 2115 int *b = (int*)a; 2116 b[1] = 3; // warn 2117 } 2118 2119.. _alpha-security-ArrayBoundV2: 2120 2121alpha.security.ArrayBoundV2 (C) 2122""""""""""""""""""""""""""""""" 2123Warn about buffer overflows (newer checker). 2124 2125.. code-block:: c 2126 2127 void test() { 2128 char *s = ""; 2129 char c = s[1]; // warn 2130 } 2131 2132 void test() { 2133 int buf[100]; 2134 int *p = buf; 2135 p = p + 99; 2136 p[1] = 1; // warn 2137 } 2138 2139 // note: compiler has internal check for this. 2140 // Use -Wno-array-bounds to suppress compiler warning. 2141 void test() { 2142 int buf[100][100]; 2143 buf[0][-1] = 1; // warn 2144 } 2145 2146 // note: requires alpha.security.taint check turned on. 2147 void test() { 2148 char s[] = "abc"; 2149 int x = getchar(); 2150 char c = s[x]; // warn: index is tainted 2151 } 2152 2153.. _alpha-security-MallocOverflow: 2154 2155alpha.security.MallocOverflow (C) 2156""""""""""""""""""""""""""""""""" 2157Check for overflows in the arguments to malloc(). 2158 2159.. code-block:: c 2160 2161 void test(int n) { 2162 void *p = malloc(n * sizeof(int)); // warn 2163 } 2164 2165 void test2(int n) { 2166 if (n > 100) // gives an upper-bound 2167 return; 2168 void *p = malloc(n * sizeof(int)); // no warning 2169 } 2170 2171.. _alpha-security-MmapWriteExec: 2172 2173alpha.security.MmapWriteExec (C) 2174"""""""""""""""""""""""""""""""" 2175Warn on mmap() calls that are both writable and executable. 2176 2177.. code-block:: c 2178 2179 void test(int n) { 2180 void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC, 2181 MAP_PRIVATE | MAP_ANON, -1, 0); 2182 // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to 2183 // exploitable memory regions, which could be overwritten with malicious 2184 // code 2185 } 2186 2187.. _alpha-security-ReturnPtrRange: 2188 2189alpha.security.ReturnPtrRange (C) 2190""""""""""""""""""""""""""""""""" 2191Check for an out-of-bound pointer being returned to callers. 2192 2193.. code-block:: c 2194 2195 static int A[10]; 2196 2197 int *test() { 2198 int *p = A + 10; 2199 return p; // warn 2200 } 2201 2202 int test(void) { 2203 int x; 2204 return x; // warn: undefined or garbage returned 2205 } 2206 2207.. _alpha-security-taint-TaintPropagation: 2208 2209alpha.security.taint.TaintPropagation (C, C++) 2210"""""""""""""""""""""""""""""""""""""""""""""" 2211Generate taint information used by other checkers. 2212A data is tainted when it comes from an unreliable source. 2213 2214.. code-block:: c 2215 2216 void test() { 2217 char x = getchar(); // 'x' marked as tainted 2218 system(&x); // warn: untrusted data is passed to a system call 2219 } 2220 2221 // note: compiler internally checks if the second param to 2222 // sprintf is a string literal or not. 2223 // Use -Wno-format-security to suppress compiler warning. 2224 void test() { 2225 char s[10], buf[10]; 2226 fscanf(stdin, "%s", s); // 's' marked as tainted 2227 2228 sprintf(buf, s); // warn: untrusted data as a format string 2229 } 2230 2231 void test() { 2232 size_t ts; 2233 scanf("%zd", &ts); // 'ts' marked as tainted 2234 int *p = (int *)malloc(ts * sizeof(int)); 2235 // warn: untrusted data as buffer size 2236 } 2237 2238alpha.unix 2239^^^^^^^^^^^ 2240 2241.. _alpha-unix-BlockInCriticalSection: 2242 2243alpha.unix.BlockInCriticalSection (C) 2244""""""""""""""""""""""""""""""""""""" 2245Check for calls to blocking functions inside a critical section. 2246Applies to: ``lock, unlock, sleep, getc, fgets, read, recv, pthread_mutex_lock,`` 2247`` pthread_mutex_unlock, mtx_lock, mtx_timedlock, mtx_trylock, mtx_unlock, lock_guard, unique_lock`` 2248 2249.. code-block:: c 2250 2251 void test() { 2252 std::mutex m; 2253 m.lock(); 2254 sleep(3); // warn: a blocking function sleep is called inside a critical 2255 // section 2256 m.unlock(); 2257 } 2258 2259.. _alpha-unix-Chroot: 2260 2261alpha.unix.Chroot (C) 2262""""""""""""""""""""" 2263Check improper use of chroot. 2264 2265.. code-block:: c 2266 2267 void f(); 2268 2269 void test() { 2270 chroot("/usr/local"); 2271 f(); // warn: no call of chdir("/") immediately after chroot 2272 } 2273 2274.. _alpha-unix-PthreadLock: 2275 2276alpha.unix.PthreadLock (C) 2277"""""""""""""""""""""""""" 2278Simple lock -> unlock checker. 2279Applies to: ``pthread_mutex_lock, pthread_rwlock_rdlock, pthread_rwlock_wrlock, lck_mtx_lock, lck_rw_lock_exclusive`` 2280``lck_rw_lock_shared, pthread_mutex_trylock, pthread_rwlock_tryrdlock, pthread_rwlock_tryrwlock, lck_mtx_try_lock, 2281lck_rw_try_lock_exclusive, lck_rw_try_lock_shared, pthread_mutex_unlock, pthread_rwlock_unlock, lck_mtx_unlock, lck_rw_done``. 2282 2283 2284.. code-block:: c 2285 2286 pthread_mutex_t mtx; 2287 2288 void test() { 2289 pthread_mutex_lock(&mtx); 2290 pthread_mutex_lock(&mtx); 2291 // warn: this lock has already been acquired 2292 } 2293 2294 lck_mtx_t lck1, lck2; 2295 2296 void test() { 2297 lck_mtx_lock(&lck1); 2298 lck_mtx_lock(&lck2); 2299 lck_mtx_unlock(&lck1); 2300 // warn: this was not the most recently acquired lock 2301 } 2302 2303 lck_mtx_t lck1, lck2; 2304 2305 void test() { 2306 if (lck_mtx_try_lock(&lck1) == 0) 2307 return; 2308 2309 lck_mtx_lock(&lck2); 2310 lck_mtx_unlock(&lck1); 2311 // warn: this was not the most recently acquired lock 2312 } 2313 2314.. _alpha-unix-SimpleStream: 2315 2316alpha.unix.SimpleStream (C) 2317""""""""""""""""""""""""""" 2318Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fclose`` 2319(demo checker, the subject of the demo (`Slides <https://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf>`_ , 2320`Video <https://youtu.be/kdxlsP5QVPw>`_) by Anna Zaks and Jordan Rose presented at the 2321`2012 LLVM Developers' Meeting <https://llvm.org/devmtg/2012-11/>`_). 2322 2323.. code-block:: c 2324 2325 void test() { 2326 FILE *F = fopen("myfile.txt", "w"); 2327 } // warn: opened file is never closed 2328 2329 void test() { 2330 FILE *F = fopen("myfile.txt", "w"); 2331 2332 if (F) 2333 fclose(F); 2334 2335 fclose(F); // warn: closing a previously closed file stream 2336 } 2337 2338.. _alpha-unix-Stream: 2339 2340alpha.unix.Stream (C) 2341""""""""""""""""""""" 2342Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,`` 2343``fsetpos, clearerr, feof, ferror, fileno``. 2344 2345.. code-block:: c 2346 2347 void test() { 2348 FILE *p = fopen("foo", "r"); 2349 } // warn: opened file is never closed 2350 2351 void test() { 2352 FILE *p = fopen("foo", "r"); 2353 fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL 2354 fclose(p); 2355 } 2356 2357 void test() { 2358 FILE *p = fopen("foo", "r"); 2359 2360 if (p) 2361 fseek(p, 1, 3); 2362 // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR 2363 2364 fclose(p); 2365 } 2366 2367 void test() { 2368 FILE *p = fopen("foo", "r"); 2369 fclose(p); 2370 fclose(p); // warn: already closed 2371 } 2372 2373 void test() { 2374 FILE *p = tmpfile(); 2375 ftell(p); // warn: stream pointer might be NULL 2376 fclose(p); 2377 } 2378 2379 2380.. _alpha-unix-cstring-BufferOverlap: 2381 2382alpha.unix.cstring.BufferOverlap (C) 2383"""""""""""""""""""""""""""""""""""" 2384Checks for overlap in two buffer arguments. Applies to: ``memcpy, mempcpy``. 2385 2386.. code-block:: c 2387 2388 void test() { 2389 int a[4] = {0}; 2390 memcpy(a + 2, a + 1, 8); // warn 2391 } 2392 2393.. _alpha-unix-cstring-NotNullTerminated: 2394 2395alpha.unix.cstring.NotNullTerminated (C) 2396"""""""""""""""""""""""""""""""""""""""" 2397Check for arguments which are not null-terminated strings; applies to: ``strlen, strnlen, strcpy, strncpy, strcat, strncat``. 2398 2399.. code-block:: c 2400 2401 void test() { 2402 int y = strlen((char *)&test); // warn 2403 } 2404 2405.. _alpha-unix-cstring-OutOfBounds: 2406 2407alpha.unix.cstring.OutOfBounds (C) 2408"""""""""""""""""""""""""""""""""" 2409Check for out-of-bounds access in string functions; applies to:`` strncopy, strncat``. 2410 2411 2412.. code-block:: c 2413 2414 void test() { 2415 int y = strlen((char *)&test); // warn 2416 } 2417 2418.. _alpha-nondeterminism-PointerIteration: 2419 2420alpha.nondeterminism.PointerIteration (C++) 2421""""""""""""""""""""""""""""""""""""""""""" 2422Check for non-determinism caused by iterating unordered containers of pointers. 2423 2424.. code-block:: c 2425 2426 void test() { 2427 int a = 1, b = 2; 2428 std::unordered_set<int *> UnorderedPtrSet = {&a, &b}; 2429 2430 for (auto i : UnorderedPtrSet) // warn 2431 f(i); 2432 } 2433 2434.. _alpha-nondeterminism-PointerSorting: 2435 2436alpha.nondeterminism.PointerSorting (C++) 2437""""""""""""""""""""""""""""""""""""""""" 2438Check for non-determinism caused by sorting of pointers. 2439 2440.. code-block:: c 2441 2442 void test() { 2443 int a = 1, b = 2; 2444 std::vector<int *> V = {&a, &b}; 2445 std::sort(V.begin(), V.end()); // warn 2446 } 2447 2448 2449alpha.WebKit 2450^^^^^^^^^^^^ 2451 2452.. _alpha-webkit-UncountedCallArgsChecker: 2453 2454alpha.webkit.UncountedCallArgsChecker 2455""""""""""""""""""""""""""""""""""""" 2456The goal of this rule is to make sure that lifetime of any dynamically allocated ref-countable object passed as a call argument spans past the end of the call. This applies to call to any function, method, lambda, function pointer or functor. Ref-countable types aren't supposed to be allocated on stack so we check arguments for parameters of raw pointers and references to uncounted types. 2457 2458Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that an argument is safe or it's considered if not a bug then bug-prone. 2459 2460 .. code-block:: cpp 2461 2462 RefCountable* provide_uncounted(); 2463 void consume(RefCountable*); 2464 2465 // In these cases we can't make sure callee won't directly or indirectly call `deref()` on the argument which could make it unsafe from such point until the end of the call. 2466 2467 void foo1() { 2468 consume(provide_uncounted()); // warn 2469 } 2470 2471 void foo2() { 2472 RefCountable* uncounted = provide_uncounted(); 2473 consume(uncounted); // warn 2474 } 2475 2476Although we are enforcing member variables to be ref-counted by `webkit.NoUncountedMemberChecker` any method of the same class still has unrestricted access to these. Since from a caller's perspective we can't guarantee a particular member won't get modified by callee (directly or indirectly) we don't consider values obtained from members safe. 2477 2478Note: It's likely this heuristic could be made more precise with fewer false positives - for example calls to free functions that don't have any parameter other than the pointer should be safe as the callee won't be able to tamper with the member unless it's a global variable. 2479 2480 .. code-block:: cpp 2481 2482 struct Foo { 2483 RefPtr<RefCountable> member; 2484 void consume(RefCountable*) { /* ... */ } 2485 void bugprone() { 2486 consume(member.get()); // warn 2487 } 2488 }; 2489 2490The implementation of this rule is a heuristic - we define a whitelist of kinds of values that are considered safe to be passed as arguments. If we can't prove an argument is safe it's considered an error. 2491 2492Allowed kinds of arguments: 2493 2494- values obtained from ref-counted objects (including temporaries as those survive the call too) 2495 2496 .. code-block:: cpp 2497 2498 RefCountable* provide_uncounted(); 2499 void consume(RefCountable*); 2500 2501 void foo() { 2502 RefPtr<RefCountable> rc = makeRef(provide_uncounted()); 2503 consume(rc.get()); // ok 2504 consume(makeRef(provide_uncounted()).get()); // ok 2505 } 2506 2507- forwarding uncounted arguments from caller to callee 2508 2509 .. code-block:: cpp 2510 2511 void foo(RefCountable& a) { 2512 bar(a); // ok 2513 } 2514 2515 Caller of ``foo()`` is responsible for ``a``'s lifetime. 2516 2517- ``this`` pointer 2518 2519 .. code-block:: cpp 2520 2521 void Foo::foo() { 2522 baz(this); // ok 2523 } 2524 2525 Caller of ``foo()`` is responsible for keeping the memory pointed to by ``this`` pointer safe. 2526 2527- constants 2528 2529 .. code-block:: cpp 2530 2531 foo(nullptr, NULL, 0); // ok 2532 2533We also define a set of safe transformations which if passed a safe value as an input provide (usually it's the return value) a safe value (or an object that provides safe values). This is also a heuristic. 2534 2535- constructors of ref-counted types (including factory methods) 2536- getters of ref-counted types 2537- member overloaded operators 2538- casts 2539- unary operators like ``&`` or ``*`` 2540 2541alpha.webkit.UncountedLocalVarsChecker 2542"""""""""""""""""""""""""""""""""""""" 2543The goal of this rule is to make sure that any uncounted local variable is backed by a ref-counted object with lifetime that is strictly larger than the scope of the uncounted local variable. To be on the safe side we require the scope of an uncounted variable to be embedded in the scope of ref-counted object that backs it. 2544 2545These are examples of cases that we consider safe: 2546 2547 .. code-block:: cpp 2548 2549 void foo1() { 2550 RefPtr<RefCountable> counted; 2551 // The scope of uncounted is EMBEDDED in the scope of counted. 2552 { 2553 RefCountable* uncounted = counted.get(); // ok 2554 } 2555 } 2556 2557 void foo2(RefPtr<RefCountable> counted_param) { 2558 RefCountable* uncounted = counted_param.get(); // ok 2559 } 2560 2561 void FooClass::foo_method() { 2562 RefCountable* uncounted = this; // ok 2563 } 2564 2565Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that an argument is safe or it's considered if not a bug then bug-prone. 2566 2567 .. code-block:: cpp 2568 2569 void foo1() { 2570 RefCountable* uncounted = new RefCountable; // warn 2571 } 2572 2573 RefCountable* global_uncounted; 2574 void foo2() { 2575 RefCountable* uncounted = global_uncounted; // warn 2576 } 2577 2578 void foo3() { 2579 RefPtr<RefCountable> counted; 2580 // The scope of uncounted is not EMBEDDED in the scope of counted. 2581 RefCountable* uncounted = counted.get(); // warn 2582 } 2583 2584We don't warn about these cases - we don't consider them necessarily safe but since they are very common and usually safe we'd introduce a lot of false positives otherwise: 2585- variable defined in condition part of an ```if``` statement 2586- variable defined in init statement condition of a ```for``` statement 2587 2588For the time being we also don't warn about uninitialized uncounted local variables. 2589 2590Debug Checkers 2591--------------- 2592 2593.. _debug-checkers: 2594 2595 2596debug 2597^^^^^ 2598 2599Checkers used for debugging the analyzer. 2600:doc:`developer-docs/DebugChecks` page contains a detailed description. 2601 2602.. _debug-AnalysisOrder: 2603 2604debug.AnalysisOrder 2605""""""""""""""""""" 2606Print callbacks that are called during analysis in order. 2607 2608.. _debug-ConfigDumper: 2609 2610debug.ConfigDumper 2611"""""""""""""""""" 2612Dump config table. 2613 2614.. _debug-DumpCFG Display: 2615 2616debug.DumpCFG Display 2617""""""""""""""""""""" 2618Control-Flow Graphs. 2619 2620.. _debug-DumpCallGraph: 2621 2622debug.DumpCallGraph 2623""""""""""""""""""" 2624Display Call Graph. 2625 2626.. _debug-DumpCalls: 2627 2628debug.DumpCalls 2629""""""""""""""" 2630Print calls as they are traversed by the engine. 2631 2632.. _debug-DumpDominators: 2633 2634debug.DumpDominators 2635"""""""""""""""""""" 2636Print the dominance tree for a given CFG. 2637 2638.. _debug-DumpLiveVars: 2639 2640debug.DumpLiveVars 2641"""""""""""""""""" 2642Print results of live variable analysis. 2643 2644.. _debug-DumpTraversal: 2645 2646debug.DumpTraversal 2647""""""""""""""""""" 2648Print branch conditions as they are traversed by the engine. 2649 2650.. _debug-ExprInspection: 2651 2652debug.ExprInspection 2653"""""""""""""""""""" 2654Check the analyzer's understanding of expressions. 2655 2656.. _debug-Stats: 2657 2658debug.Stats 2659""""""""""" 2660Emit warnings with analyzer statistics. 2661 2662.. _debug-TaintTest: 2663 2664debug.TaintTest 2665""""""""""""""" 2666Mark tainted symbols as such. 2667 2668.. _debug-ViewCFG: 2669 2670debug.ViewCFG 2671""""""""""""" 2672View Control-Flow Graphs using GraphViz. 2673 2674.. _debug-ViewCallGraph: 2675 2676debug.ViewCallGraph 2677""""""""""""""""""" 2678View Call Graph using GraphViz. 2679 2680.. _debug-ViewExplodedGraph: 2681 2682debug.ViewExplodedGraph 2683""""""""""""""""""""""" 2684View Exploded Graphs using GraphViz. 2685 2686