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