1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 2 "http://www.w3.org/TR/html4/strict.dtd"> 3<html> 4<head> 5 <title>Alpha Checks</title> 6 <link type="text/css" rel="stylesheet" href="menu.css"> 7 <link type="text/css" rel="stylesheet" href="content.css"> 8 <script type="text/javascript" src="scripts/menu.js"></script> 9 <script type="text/javascript" src="scripts/expandcollapse.js"></script> 10 <style type="text/css"> 11 tr:first-child { width:20%; } 12 </style> 13</head> 14<body onload="initExpandCollapse()"> 15 16<div id="page"> 17<!--#include virtual="menu.html.incl"--> 18 19<div id="content"> 20<h1>Alpha Checkers</h1> 21Experimental checkers in addition to the <a href = "available_checks.html"> 22Default Checkers</a>. These are checkers with known issues or limitations that 23keep them from being on by default. They are likely to have false positives. 24Bug reports are welcome but will likely not be investigated for some time. 25Patches welcome! 26<ul> 27<li><a href="#clone_alpha_checkers">Clone Alpha Checkers</a></li> 28<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li> 29<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li> 30<li><a href="#llvm_alpha_checkers">LLVM Checkers</a></li> 31<li><a href="#valist_alpha_checkers">Variable Argument Alpha Checkers</a></li> 32<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li> 33<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li> 34<li><a href="#security_alpha_checkers">Security Alpha Checkers</a></li> 35<li><a href="#unix_alpha_checkers">Unix Alpha Checkers</a></li> 36<li><a href="#nondeterminism_alpha_checkers">Non-determinism Alpha Checkers</a></li> 37</ul> 38 39<!-- ============================= clone alpha ============================= --> 40 41<h3 id="clone_alpha_checkers">Clone Alpha Checkers</h3> 42<table class="checkers"> 43<colgroup><col class="namedescr"><col class="example"></colgroup> 44<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 45 46<tbody> 47<tr><td><a id="alpha.clone.CloneChecker"><div class="namedescr expandable"><span class="name"> 48alpha.clone.CloneChecker</span><span class="lang"> 49(C, C++, ObjC)</span><div class="descr"> 50Reports similar pieces of code.</div></div></a></td> 51<td><div class="exampleContainer expandable"> 52<div class="example"><pre> 53void log(); 54 55int max(int a, int b) { // warn 56 log(); 57 if (a > b) 58 return a; 59 return b; 60} 61 62int maxClone(int x, int y) { // similar code here 63 log(); 64 if (x > y) 65 return x; 66 return y; 67} 68</pre></div></div></td></tr> 69</tbody></table> 70 71<!-- ============================= core alpha ============================= --> 72<h3 id="core_alpha_checkers">Core Alpha Checkers</h3> 73<table class="checkers"> 74<colgroup><col class="namedescr"><col class="example"></colgroup> 75<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 76 77<tbody> 78<tr><td><a id="alpha.core.BoolAssignment"><div class="namedescr expandable"><span class="name"> 79alpha.core.BoolAssignment</span><span class="lang"> 80(ObjC)</span><div class="descr"> 81Warn about assigning non-{0,1} values to boolean variables.</div></div></a></td> 82<td><div class="exampleContainer expandable"> 83<div class="example"><pre> 84void test() { 85 BOOL b = -1; // warn 86} 87</pre></div></div></td></tr> 88 89 90<tr><td><a id="alpha.core.CallAndMessageUnInitRefArg"><div class="namedescr expandable"><span class="name"> 91alpha.core.CallAndMessageUnInitRefArg</span><span class="lang"> 92(C, C++)</span><div class="descr"> 93Check for uninitialized arguments in function calls and Objective-C 94message expressions.</div></div></a></td> 95<td><div class="exampleContainer expandable"> 96<div class="example"><pre> 97void test(void) { 98 int t; 99 int &p = t; 100 int &s = p; 101 int &q = s; 102 foo(q); // warn 103} 104</pre></div><div class="separator"></div> 105<div class="example"><pre> 106void test(void) { 107 int x; 108 foo(&x); // warn 109} 110</pre></div></div></td></tr> 111 112 113<tr><td><a id="alpha.core.CastSize"><div class="namedescr expandable"><span class="name"> 114alpha.core.CastSize</span><span class="lang"> 115(C)</span><div class="descr"> 116Check when casting a malloc'ed type T, whether the size is a multiple of the 117size of T (Works only with <span class="name">unix.Malloc</span> 118or <span class="name">alpha.unix.MallocWithAnnotations</span> 119checks enabled).</div></div></a></td> 120<td><div class="exampleContainer expandable"> 121<div class="example"><pre> 122void test() { 123 int *x = (int *)malloc(11); // warn 124} 125</pre></div></div></td></tr> 126 127 128<tr><td><a id="alpha.core.CastToStruct"><div class="namedescr expandable"><span class="name"> 129alpha.core.CastToStruct</span><span class="lang"> 130(C, C++)</span><div class="descr"> 131Check for cast from non-struct pointer to struct pointer.</div></div></a></td> 132<td><div class="exampleContainer expandable"> 133<div class="example"><pre> 134// C 135struct s {}; 136 137void test(int *p) { 138 struct s *ps = (struct s *) p; // warn 139} 140</pre></div><div class="separator"></div> 141<div class="example"><pre> 142// C++ 143class c {}; 144 145void test(int *p) { 146 c *pc = (c *) p; // warn 147} 148</pre></div></div></td></tr> 149 150 151<tr><td><a id="alpha.core.Conversion"><div class="namedescr expandable"><span class="name"> 152alpha.core.Conversion</span><span class="lang"> 153(C, C++, ObjC)</span><div class="descr"> 154Loss of sign or precision in implicit conversions</div></div></a></td> 155<td><div class="exampleContainer expandable"> 156<div class="example"><pre> 157void test(unsigned U, signed S) { 158 if (S > 10) { 159 if (U < S) { 160 } 161 } 162 if (S < -10) { 163 if (U < S) { // warn (loss of sign) 164 } 165 } 166} 167</pre></div><div class="separator"></div> 168<div class="example"><pre> 169void test() { 170 long long A = 1LL << 60; 171 short X = A; // warn (loss of precision) 172} 173</pre></div></div></td></tr> 174 175 176<tr><td><a id="alpha.core.DynamicTypeChecker"><div class="namedescr expandable"><span class="name"> 177alpha.core.DynamicTypeChecker</span><span class="lang"> 178(ObjC)</span><div class="descr"> 179Check for cases where the dynamic and the static type of an 180object are unrelated.</div></div></a></td> 181<td><div class="exampleContainer expandable"> 182<div class="example"><pre> 183id date = [NSDate date]; 184 185// Warning: Object has a dynamic type 'NSDate *' which is 186// incompatible with static type 'NSNumber *'" 187NSNumber *number = date; 188[number doubleValue]; 189</pre></div></div></td></tr> 190 191 192<tr><td><a id="alpha.core.FixedAddr"><div class="namedescr expandable"><span class="name"> 193alpha.core.FixedAddr</span><span class="lang"> 194(C)</span><div class="descr"> 195Check for assignment of a fixed address to a pointer.</div></div></a></td> 196<td><div class="exampleContainer expandable"> 197<div class="example"><pre> 198void test() { 199 int *p; 200 p = (int *) 0x10000; // warn 201} 202</pre></div></div></td></tr> 203 204 205<tr><td><a id="alpha.core.IdenticalExpr"><div class="namedescr expandable"><span class="name"> 206alpha.core.IdenticalExpr</span><span class="lang"> 207(C, C++)</span><div class="descr"> 208Warn about suspicious uses of identical expressions.</div></div></a></td> 209<td><div class="exampleContainer expandable"> 210<div class="example"><pre> 211// C 212void test() { 213 int a = 5; 214 int b = a | 4 | a; // warn: identical expr on both sides 215} 216</pre></div><div class="separator"></div> 217<div class="example"><pre> 218// C++ 219bool f(void); 220 221void test(bool b) { 222 int i = 10; 223 if (f()) { // warn: true and false branches are identical 224 do { 225 i--; 226 } while (f()); 227 } else { 228 do { 229 i--; 230 } while (f()); 231 } 232} 233</pre></div></div></td></tr> 234 235 236<tr><td><a id="alpha.core.PointerArithm"><div class="namedescr expandable"><span class="name"> 237alpha.core.PointerArithm</span><span class="lang"> 238(C)</span><div class="descr"> 239Check for pointer arithmetic on locations other than array 240elements.</div></div></a></td> 241<td><div class="exampleContainer expandable"> 242<div class="example"><pre> 243void test() { 244 int x; 245 int *p; 246 p = &x + 1; // warn 247} 248</pre></div></div></td></tr> 249 250 251<tr><td><a id="alpha.core.PointerSub"><div class="namedescr expandable"><span class="name"> 252alpha.core.PointerSub</span><span class="lang"> 253(C)</span><div class="descr"> 254Check for pointer subtractions on two pointers pointing to different memory 255chunks.</div></div></a></td> 256<td><div class="exampleContainer expandable"> 257<div class="example"><pre> 258void test() { 259 int x, y; 260 int d = &y - &x; // warn 261} 262</pre></div></div></td></tr> 263 264 265<tr><td><a id="alpha.core.SizeofPtr"><div class="namedescr expandable"><span class="name"> 266alpha.core.SizeofPtr</span><span class="lang"> 267(C)</span><div class="descr"> 268Warn about unintended use of <code>sizeof()</code> on pointer 269expressions.</div></div></a></td> 270<td><div class="exampleContainer expandable"> 271<div class="example"><pre> 272struct s {}; 273 274int test(struct s *p) { 275 return sizeof(p); 276 // warn: sizeof(ptr) can produce an unexpected result 277} 278</pre></div></div></td></tr> 279 280 281<tr><td><a id="alpha.core.StackAddressAsyncEscape"><div class="namedescr expandable"><span class="name"> 282alpha.core.StackAddressAsyncEscape</span><span class="lang"> 283(C)</span><div class="descr"> 284Check that addresses to stack memory do not escape the function that involves 285<code>dispatch_after</code> or <code>dispatch_async</code>. This checker is 286a part of core.StackAddressEscape, but is 287<a href=https://reviews.llvm.org/D41042>temporarily disabled</a> until some 288false positives are fixed.</div></div></a></td> 289<td><div class="exampleContainer expandable"> 290<div class="example"><pre> 291dispatch_block_t test_block_inside_block_async_leak() { 292 int x = 123; 293 void (^inner)(void) = ^void(void) { 294 int y = x; 295 ++y; 296 }; 297 void (^outer)(void) = ^void(void) { 298 int z = x; 299 ++z; 300 inner(); 301 }; 302 return outer; // warn: address of stack-allocated block is captured by a 303 // returned block 304} 305</pre></div></div></td></tr> 306 307 308<tr><td><a id="alpha.core.TestAfterDivZero"><div class="namedescr expandable"><span class="name"> 309alpha.core.TestAfterDivZero</span><span class="lang"> 310(C, C++, ObjC)</span><div class="descr"> 311Check for division by variable that is later compared against 0. 312Either the comparison is useless or there is division by zero. 313</div></div></a></td> 314<td><div class="exampleContainer expandable"> 315<div class="example"><pre> 316void test(int x) { 317 var = 77 / x; 318 if (x == 0) { } // warn 319} 320</pre></div></div></td></tr> 321 322 323</tbody></table> 324 325<!-- =========================== cplusplus alpha =========================== --> 326<h3 id="cplusplus_alpha_checkers">C++ Alpha Checkers</h3> 327<table class="checkers"> 328<colgroup><col class="namedescr"><col class="example"></colgroup> 329<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 330<tbody> 331 332 333<tr><td><a id="alpha.cplusplus.DeleteWithNonVirtualDtor"><div class="namedescr expandable"><span class="name"> 334alpha.cplusplus.DeleteWithNonVirtualDtor</span><span class="lang"> 335(C++)</span><div class="descr"> 336Reports destructions of polymorphic objects with a non-virtual destructor in 337their base class 338</div></div></a></td> 339<td><div class="exampleContainer expandable"> 340<div class="example"><pre> 341NonVirtual *create() { 342 NonVirtual *x = new NVDerived(); // note: conversion from derived to base 343 // happened here 344 return x; 345} 346 347void sink(NonVirtual *x) { 348 delete x; // warn: destruction of a polymorphic object with no virtual 349 // destructor 350} 351</pre></div></div></td></tr> 352 353<tr><td><a id="alpha.cplusplus.EnumCastOutOfRange"><div class="namedescr expandable"><span class="name"> 354alpha.cplusplus.EnumCastOutOfRange</span><span class="lang"> 355(C++)</span><div class="descr"> 356 Check for integer to enumeration casts that could result in undefined values. 357</div></div></a></td> 358 <td><div class="exampleContainer expandable"> 359 <div class="example"><pre> 360enum TestEnum { 361 A = 0 362}; 363 364void foo() { 365 TestEnum t = static_cast<TestEnum>(-1); 366 // warn: the value provided to the cast expression is not in 367 the valid range of values for the enum 368} 369</pre></div></div></td></tr> 370 371 372<tr><td><a id="alpha.cplusplus.InvalidatedIterator"><div class="namedescr expandable"><span class="name"> 373alpha.cplusplus.InvalidatedIterator</span><span class="lang"> 374(C++)</span><div class="descr"> 375Check for use of invalidated iterators. 376</div></div></a></td> 377<td><div class="exampleContainer expandable"> 378<div class="example"><pre> 379void bad_copy_assign_operator_list1(std::list<int> &L1, 380 const std::list<int> &L2) { 381 auto i0 = L1.cbegin(); 382 L1 = L2; 383 *i0; // warn: invalidated iterator accessed 384} 385</pre></div></div></td></tr> 386 387 388<tr><td><a id="alpha.cplusplus.IteratorRange"><div class="namedescr expandable"><span class="name"> 389alpha.cplusplus.IteratorRange</span><span class="lang"> 390(C++)</span><div class="descr"> 391Check for iterators used outside their valid ranges. 392</div></div></a></td> 393<td><div class="exampleContainer expandable"> 394<div class="example"><pre> 395void simple_bad_end(const std::vector<int> &v) { 396 auto i = v.end(); 397 *i; // warn: iterator accessed outside of its range 398} 399</pre></div></div></td></tr> 400 401 402<tr><td><a id="alpha.cplusplus.MismatchedIterator"><div class="namedescr expandable"><span class="name"> 403alpha.cplusplus.MismatchedIterator</span><span class="lang"> 404(C++)</span><div class="descr"> 405Check for use of iterators of different containers where iterators of the same 406container are expected. 407</div></div></a></td> 408<td><div class="exampleContainer expandable"> 409<div class="example"><pre> 410void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) { 411 v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed 412 // using foreign 413 // iterator argument 414 v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of 415 // different containers 416 // used where the same 417 // container is 418 // expected 419 v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of 420 // different containers 421 // used where the same 422 // container is 423 // expected 424} 425</pre></div></div></td></tr> 426 427 428<tr><td><a id="alpha.cplusplus.Move"><div class="namedescr expandable"><span class="name"> 429alpha.cplusplus.Move</span><span class="lang"> 430(C++)</span><div class="descr"> 431Method calls on a moved-from object and copying a moved-from object will be 432reported. 433</div></div></a></td> 434<td><div class="exampleContainer expandable"> 435<div class="example"><pre> 436struct A { 437 void foo() {} 438}; 439 440void f() { 441 A a; 442 A b = std::move(a); // note: 'a' became 'moved-from' here 443 a.foo(); // warn: method call on a 'moved-from' object 'a' 444} 445</pre></div></div></td></tr> 446 447 448</tbody></table> 449 450 451<!-- =========================== dead code alpha =========================== --> 452<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3> 453<table class="checkers"> 454<colgroup><col class="namedescr"><col class="example"></colgroup> 455<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 456 457<tbody> 458<tr><td><a id="alpha.deadcode.UnreachableCode"><div class="namedescr expandable"><span class="name"> 459alpha.deadcode.UnreachableCode</span><span class="lang"> 460(C, C++, ObjC)</span><div class="descr"> 461Check unreachable code.</div></div></a></td> 462<td><div class="exampleContainer expandable"> 463<div class="example"><pre> 464// C 465int test() { 466 int x = 1; 467 while(x); 468 return x; // warn 469} 470</pre></div><div class="separator"></div> 471<div class="example"><pre> 472// C++ 473void test() { 474 int a = 2; 475 476 while (a > 1) 477 a--; 478 479 if (a > 1) 480 a++; // warn 481} 482</pre></div><div class="separator"></div> 483<div class="example"><pre> 484// Objective-C 485void test(id x) { 486 return; 487 [x retain]; // warn 488} 489</pre></div></div></td></tr> 490</tbody></table> 491 492<!-- =========================== llvm alpha =========================== --> 493<h3 id="llvm_alpha_checkers">LLVM Checkers</h3> 494<table class="checkers"> 495<colgroup><col class="namedescr"><col class="example"></colgroup> 496<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 497 498<tbody> 499<tr><td><a id="alpha.llvm.Conventions"><div class="namedescr expandable"><span class="name"> 500alpha.llvm.Conventions</span><span class="lang"> 501(C)</span><div class="descr"> 502Check code for LLVM codebase conventions: 503<ul> 504 <li>A <code>StringRef</code> should not be bound to a temporary std::string 505 whose lifetime is shorter than the <code>StringRef</code>'s.</li> 506 <li>Clang AST nodes should not have fields that can allocate memory.</li> 507</ul> 508</div></div></a></td> 509<td><div class="exampleContainer expandable"> 510<div class="example"><pre> 511<!-- TODO: Add examples, as currently it's hard to get this checker working. --> 512</pre></div></div></td></tr> 513 514</tbody></table> 515 516 517<!-- ============================== OS X alpha ============================== --> 518<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3> 519<table class="checkers"> 520<colgroup><col class="namedescr"><col class="example"></colgroup> 521<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 522 523<tbody> 524<tr><td><a id="alpha.osx.cocoa.DirectIvarAssignment"><div class="namedescr expandable"><span class="name"> 525alpha.osx.cocoa.DirectIvarAssignment</span><span class="lang"> 526(ObjC)</span><div class="descr"> 527Check that Objective C properties follow the following rule: the property 528should be set with the setter, not though a direct assignment.</div></div></a></td> 529<td><div class="exampleContainer expandable"> 530<div class="example"><pre> 531@interface MyClass : NSObject {} 532@property (readonly) id A; 533- (void) foo; 534@end 535 536@implementation MyClass 537- (void) foo { 538 _A = 0; // warn 539} 540@end 541</pre></div></div></td></tr> 542 543 544<tr><td><a id="alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions"><div class="namedescr expandable"><span class="name"> 545alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions</span><span class="lang"> 546(ObjC)</span><div class="descr"> 547Check for direct assignments to instance variables in the methods annotated 548with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></a></td> 549<td><div class="exampleContainer expandable"> 550<div class="example"><pre> 551@interface MyClass : NSObject {} 552@property (readonly) id A; 553- (void) fAnnotated __attribute__(( 554 annotate("objc_no_direct_instance_variable_assignment"))); 555- (void) fNotAnnotated; 556@end 557 558@implementation MyClass 559- (void) fAnnotated { 560 _A = 0; // warn 561} 562- (void) fNotAnnotated { 563 _A = 0; // no warn 564} 565@end 566</pre></div></div></td></tr> 567 568 569<tr><td><a id="alpha.osx.cocoa.InstanceVariableInvalidation"><div class="namedescr expandable"><span class="name"> 570alpha.osx.cocoa.InstanceVariableInvalidation</span><span class="lang"> 571(ObjC)</span><div class="descr"> 572Check that the invalidatable instance variables are invalidated in the methods 573annotated with <code>objc_instance_variable_invalidator</code>.</div></div></a></td> 574<td><div class="exampleContainer expandable"> 575<div class="example"><pre> 576@protocol Invalidation <NSObject> 577- (void) invalidate 578 __attribute__((annotate("objc_instance_variable_invalidator"))); 579@end 580 581@interface InvalidationImpObj : NSObject <Invalidation> 582@end 583 584@interface SubclassInvalidationImpObj : InvalidationImpObj { 585 InvalidationImpObj *var; 586} 587- (void)invalidate; 588@end 589 590@implementation SubclassInvalidationImpObj 591- (void) invalidate {} 592@end 593// warn: var needs to be invalidated or set to nil 594</pre></div></div></td></tr> 595 596 597<tr><td><a id="alpha.osx.cocoa.MissingInvalidationMethod"><div class="namedescr expandable"><span class="name"> 598alpha.osx.cocoa.MissingInvalidationMethod</span><span class="lang"> 599(ObjC)</span><div class="descr"> 600Check that the invalidation methods are present in classes that contain 601invalidatable instance variables.</div></div></a></td> 602<td><div class="exampleContainer expandable"> 603<div class="example"><pre> 604@protocol Invalidation <NSObject> 605- (void)invalidate 606 __attribute__((annotate("objc_instance_variable_invalidator"))); 607@end 608 609@interface NeedInvalidation : NSObject <Invalidation> 610@end 611 612@interface MissingInvalidationMethodDecl : NSObject { 613 NeedInvalidation *Var; // warn 614} 615@end 616 617@implementation MissingInvalidationMethodDecl 618@end 619</pre></div></div></td></tr> 620 621 622<tr><td><a id="alpha.osx.cocoa.localizability.PluralMisuseChecker"><div class="namedescr expandable"><span class="name"> 623alpha.osx.cocoa.localizability.PluralMisuseChecker</span><span class="lang"> 624(ObjC)</span><div class="descr"> 625Warns against using one vs. many plural pattern in code 626when generating localized strings. 627</div></div></a></td> 628<td><div class="exampleContainer expandable"> 629<div class="example"><pre> 630NSString *reminderText = 631 NSLocalizedString(@"None", @"Indicates no reminders"); 632if (reminderCount == 1) { 633 // Warning: Plural cases are not supported across all languages. 634 // Use a .stringsdict file instead 635 reminderText = 636 NSLocalizedString(@"1 Reminder", @"Indicates single reminder"); 637} else if (reminderCount >= 2) { 638 // Warning: Plural cases are not supported across all languages. 639 // Use a .stringsdict file instead 640 reminderText = 641 [NSString stringWithFormat: 642 NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"), 643 reminderCount]; 644} 645</pre></div></div></td></tr> 646 647</tbody></table> 648 649<!-- =========================== security alpha =========================== --> 650<h3 id="security_alpha_checkers">Security Alpha Checkers</h3> 651<table class="checkers"> 652<colgroup><col class="namedescr"><col class="example"></colgroup> 653<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 654 655<tbody> 656<tr><td><a id="alpha.security.ArrayBound"><div class="namedescr expandable"><span class="name"> 657alpha.security.ArrayBound</span><span class="lang"> 658(C)</span><div class="descr"> 659Warn about buffer overflows (older checker).</div></div></a></td> 660<td><div class="exampleContainer expandable"> 661<div class="example"><pre> 662void test() { 663 char *s = ""; 664 char c = s[1]; // warn 665} 666</pre></div><div class="separator"></div> 667<div class="example"><pre> 668struct seven_words { 669 int c[7]; 670}; 671 672void test() { 673 struct seven_words a, *p; 674 p = &a; 675 p[0] = a; 676 p[1] = a; 677 p[2] = a; // warn 678} 679</pre></div><div class="separator"></div> 680<div class="example"><pre> 681// note: requires unix.Malloc or 682// alpha.unix.MallocWithAnnotations checks enabled. 683void test() { 684 int *p = malloc(12); 685 p[3] = 4; // warn 686} 687</pre></div><div class="separator"></div> 688<div class="example"><pre> 689void test() { 690 char a[2]; 691 int *b = (int*)a; 692 b[1] = 3; // warn 693} 694</pre></div></div></td></tr> 695 696 697<tr><td><a id="alpha.security.ArrayBoundV2"><div class="namedescr expandable"><span class="name"> 698alpha.security.ArrayBoundV2</span><span class="lang"> 699(C)</span><div class="descr"> 700Warn about buffer overflows (newer checker).</div></div></a></td> 701<td><div class="exampleContainer expandable"> 702<div class="example"><pre> 703void test() { 704 char *s = ""; 705 char c = s[1]; // warn 706} 707</pre></div><div class="separator"></div> 708<div class="example"><pre> 709void test() { 710 int buf[100]; 711 int *p = buf; 712 p = p + 99; 713 p[1] = 1; // warn 714} 715</pre></div><div class="separator"></div> 716<div class="example"><pre> 717// note: compiler has internal check for this. 718// Use -Wno-array-bounds to suppress compiler warning. 719void test() { 720 int buf[100][100]; 721 buf[0][-1] = 1; // warn 722} 723</pre></div><div class="separator"></div> 724<div class="example"><pre> 725// note: requires alpha.security.taint check turned on. 726void test() { 727 char s[] = "abc"; 728 int x = getchar(); 729 char c = s[x]; // warn: index is tainted 730} 731</pre></div></div></td></tr> 732 733 734<tr><td><a id="alpha.security.MallocOverflow"><div class="namedescr expandable"><span class="name"> 735alpha.security.MallocOverflow</span><span class="lang"> 736(C)</span><div class="descr"> 737Check for overflows in the arguments to <code>malloc()</code>.</div></div></a></td> 738<td><div class="exampleContainer expandable"> 739<div class="example"><pre> 740void test(int n) { 741 void *p = malloc(n * sizeof(int)); // warn 742} 743</pre></div></div></td></tr> 744 745 746<tr><td><a id="alpha.security.MmapWriteExec"><div class="namedescr expandable"><span class="name"> 747alpha.security.MmapWriteExec</span><span class="lang"> 748(C)</span><div class="descr"> 749Warn on <code>mmap()<code> calls that are both writable and executable. 750</div></div></a></td> 751<td><div class="exampleContainer expandable"> 752<div class="example"><pre> 753void test(int n) { 754 void *c = mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC, 755 MAP_PRIVATE | MAP_ANON, -1, 0); 756 // warn: Both PROT_WRITE and PROT_EXEC flags are set. This can lead to 757 // exploitable memory regions, which could be overwritten with malicious 758 // code 759} 760</pre></div></div></td></tr> 761 762 763<tr><td><a id="alpha.security.ReturnPtrRange"><div class="namedescr expandable"><span class="name"> 764alpha.security.ReturnPtrRange</span><span class="lang"> 765(C)</span><div class="descr"> 766Check for an out-of-bound pointer being returned to callers.</div></div></a></td> 767<td><div class="exampleContainer expandable"> 768<div class="example"><pre> 769static int A[10]; 770 771int *test() { 772 int *p = A + 10; 773 return p; // warn 774} 775</pre></div><div class="separator"></div> 776<div class="example"><pre> 777int test(void) { 778 int x; 779 return x; // warn: undefined or garbage returned 780} 781</pre></div></div></td></tr> 782 783 784<tr><td><a id="alpha.security.taint.TaintPropagation"><div class="namedescr expandable"><span class="name"> 785alpha.security.taint.TaintPropagation</span><span class="lang"> 786(C)</span><div class="descr"> 787Generate taint information used by other checkers.</div></div></a></td> 788<td><div class="exampleContainer expandable"> 789<div class="example"><pre> 790void test() { 791 char x = getchar(); // 'x' marked as tainted 792 system(&x); // warn: untrusted data is passed to a system call 793} 794</pre></div><div class="separator"></div> 795<div class="example"><pre> 796// note: compiler internally checks if the second param to 797// sprintf is a string literal or not. 798// Use -Wno-format-security to suppress compiler warning. 799void test() { 800 char s[10], buf[10]; 801 fscanf(stdin, "%s", s); // 's' marked as tainted 802 803 sprintf(buf, s); // warn: untrusted data as a format string 804} 805</pre></div><div class="separator"></div> 806<div class="example"><pre> 807void test() { 808 size_t ts; 809 scanf("%zd", &ts); // 'ts' marked as tainted 810 int *p = (int *)malloc(ts * sizeof(int)); 811 // warn: untrusted data as buffer size 812} 813</pre></div></div></td></tr> 814 815</tbody></table> 816 817<!-- ============================= unix alpha ============================= --> 818<h3 id="unix_alpha_checkers">Unix Alpha Checkers</h3> 819<table class="checkers"> 820<colgroup><col class="namedescr"><col class="example"></colgroup> 821<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 822<tbody> 823 824 825<tr><td><a id="alpha.unix.BlockInCriticalSection"><div class="namedescr expandable"><span class="name"> 826alpha.unix.BlockInCriticalSection</span><span class="lang"> 827(C)</span><div class="descr"> 828Check for calls to blocking functions inside a critical section. Applies to: 829<div class=functions> 830lock<br> 831unlock<br> 832sleep<br> 833getc<br> 834fgets<br> 835read<br> 836revc<br> 837pthread_mutex_lock<br> 838pthread_mutex_unlock<br> 839mtx_lock<br> 840mtx_timedlock<br> 841mtx_trylock<br> 842mtx_unlock<br> 843lock_guard<br> 844unique_lock</div> 845</div></div></a></td> 846<td><div class="exampleContainer expandable"> 847<div class="example"><pre> 848void test() { 849 std::mutex m; 850 m.lock(); 851 sleep(3); // warn: a blocking function sleep is called inside a critical 852 // section 853 m.unlock(); 854} 855</pre></div></div></td></tr> 856 857 858<tr><td><a id="alpha.unix.Chroot"><div class="namedescr expandable"><span class="name"> 859alpha.unix.Chroot</span><span class="lang"> 860(C)</span><div class="descr"> 861Check improper use of <code>chroot</code>.</div></div></a></td> 862<td><div class="exampleContainer expandable"> 863<div class="example"><pre> 864void f(); 865 866void test() { 867 chroot("/usr/local"); 868 f(); // warn: no call of chdir("/") immediately after chroot 869} 870</pre></div></div></td></tr> 871 872 873<tr><td><a id="alpha.unix.PthreadLock"><div class="namedescr expandable"><span class="name"> 874alpha.unix.PthreadLock</span><span class="lang"> 875(C)</span><div class="descr"> 876Simple lock -> unlock checker; applies to:<div class=functions> 877pthread_mutex_lock<br> 878pthread_rwlock_rdlock<br> 879pthread_rwlock_wrlock<br> 880lck_mtx_lock<br> 881lck_rw_lock_exclusive<br> 882lck_rw_lock_shared<br> 883pthread_mutex_trylock<br> 884pthread_rwlock_tryrdlock<br> 885pthread_rwlock_tryrwlock<br> 886lck_mtx_try_lock<br> 887lck_rw_try_lock_exclusive<br> 888lck_rw_try_lock_shared<br> 889pthread_mutex_unlock<br> 890pthread_rwlock_unlock<br> 891lck_mtx_unlock<br> 892lck_rw_done</div></div></div></a></td> 893<td><div class="exampleContainer expandable"> 894<div class="example"><pre> 895pthread_mutex_t mtx; 896 897void test() { 898 pthread_mutex_lock(&mtx); 899 pthread_mutex_lock(&mtx); 900 // warn: this lock has already been acquired 901} 902</pre></div><div class="separator"></div> 903<div class="example"><pre> 904lck_mtx_t lck1, lck2; 905 906void test() { 907 lck_mtx_lock(&lck1); 908 lck_mtx_lock(&lck2); 909 lck_mtx_unlock(&lck1); 910 // warn: this was not the most recently acquired lock 911} 912</pre></div><div class="separator"></div> 913<div class="example"><pre> 914lck_mtx_t lck1, lck2; 915 916void test() { 917 if (lck_mtx_try_lock(&lck1) == 0) 918 return; 919 920 lck_mtx_lock(&lck2); 921 lck_mtx_unlock(&lck1); 922 // warn: this was not the most recently acquired lock 923} 924</pre></div></div></td></tr> 925 926 927<tr><td><a id="alpha.unix.SimpleStream"><div class="namedescr expandable"><span class="name"> 928alpha.unix.SimpleStream</span><span class="lang"> 929(C)</span><div class="descr"> 930Check for misuses of stream APIs:<div class=functions> 931fopen<br> 932fclose</div>(demo checker, the subject of the demo 933(<a href="https://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a> 934,<a href="https://youtu.be/kdxlsP5QVPw">Video</a>) 935by Anna Zaks and Jordan Rose presented at the <a href="https://llvm.org/devmtg/2012-11/"> 9362012 LLVM Developers' Meeting).</a></div></div></a></td> 937<td><div class="exampleContainer expandable"> 938<div class="example"><pre> 939void test() { 940 FILE *F = fopen("myfile.txt", "w"); 941} // warn: opened file is never closed 942</pre></div><div class="separator"></div> 943<div class="example"><pre> 944void test() { 945 FILE *F = fopen("myfile.txt", "w"); 946 947 if (F) 948 fclose(F); 949 950 fclose(F); // warn: closing a previously closed file stream 951} 952</pre></div></div></td></tr> 953 954 955<tr><td><a id="alpha.unix.Stream"><div class="namedescr expandable"><span class="name"> 956alpha.unix.Stream</span><span class="lang"> 957(C)</span><div class="descr"> 958Check stream handling functions:<div class=functions>fopen<br> 959tmpfile<br> 960fclose<br> 961fread<br> 962fwrite<br> 963fseek<br> 964ftell<br> 965rewind<br> 966fgetpos<br> 967fsetpos<br> 968clearerr<br> 969feof<br> 970ferror<br> 971fileno</div></div></div></a></td> 972<td><div class="exampleContainer expandable"> 973<div class="example"><pre> 974void test() { 975 FILE *p = fopen("foo", "r"); 976} // warn: opened file is never closed 977</pre></div><div class="separator"></div> 978<div class="example"><pre> 979void test() { 980 FILE *p = fopen("foo", "r"); 981 fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL 982 fclose(p); 983} 984</pre></div><div class="separator"></div> 985<div class="example"><pre> 986void test() { 987 FILE *p = fopen("foo", "r"); 988 989 if (p) 990 fseek(p, 1, 3); 991 // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR 992 993 fclose(p); 994} 995</pre></div><div class="separator"></div> 996<div class="example"><pre> 997void test() { 998 FILE *p = fopen("foo", "r"); 999 fclose(p); 1000 fclose(p); // warn: already closed 1001} 1002</pre></div><div class="separator"></div> 1003<div class="example"><pre> 1004void test() { 1005 FILE *p = tmpfile(); 1006 ftell(p); // warn: stream pointer might be NULL 1007 fclose(p); 1008} 1009</pre></div></div></td></tr> 1010 1011 1012<tr><td><a id="alpha.unix.cstring.BufferOverlap"><div class="namedescr expandable"><span class="name"> 1013alpha.unix.cstring.BufferOverlap</span><span class="lang"> 1014(C)</span><div class="descr"> 1015Checks for overlap in two buffer arguments; applies to:<div class=functions> 1016memcpy<br> 1017mempcpy</div></div></div></a></td> 1018<td><div class="exampleContainer expandable"> 1019<div class="example"><pre> 1020void test() { 1021 int a[4] = {0}; 1022 memcpy(a + 2, a + 1, 8); // warn 1023} 1024</pre></div></div></td></tr> 1025 1026 1027<tr><td><a id="alpha.unix.cstring.NotNullTerminated"><div class="namedescr expandable"><span class="name"> 1028alpha.unix.cstring.NotNullTerminated</span><span class="lang"> 1029(C)</span><div class="descr"> 1030Check for arguments which are not null-terminated strings; applies 1031to:<div class=functions> 1032strlen<br> 1033strnlen<br> 1034strcpy<br> 1035strncpy<br> 1036strcat<br> 1037strncat</div></div></div></td> 1038<td><div class="exampleContainer expandable"> 1039<div class="example"><pre> 1040void test() { 1041 int y = strlen((char *)&test); // warn 1042} 1043</pre></div></div></a></td></tr> 1044 1045 1046<tr><td><a id="alpha.unix.cstring.OutOfBounds"><div class="namedescr expandable"><span class="name"> 1047alpha.unix.cstring.OutOfBounds</span><span class="lang"> 1048(C)</span><div class="descr"> 1049Check for out-of-bounds access in string functions; applies 1050to:<div class=functions> 1051strncopy<br> 1052strncat</div></div></div></a></td> 1053<td><div class="exampleContainer expandable"> 1054<div class="example"><pre> 1055void test(char *y) { 1056 char x[4]; 1057 if (strlen(y) == 4) 1058 strncpy(x, y, 5); // warn 1059} 1060</pre></div></div></td></tr> 1061 1062</tbody></table> 1063 1064<!-- =========================== nondeterminism alpha =========================== --> 1065<h3 id="nondeterminism_alpha_checkers">Non-determinism Alpha Checkers</h3> 1066<table class="checkers"> 1067<colgroup><col class="namedescr"><col class="example"></colgroup> 1068<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 1069 1070<tbody> 1071<tr><td><a id="alpha.nondeterminism.PointerIteration"><div class="namedescr expandable"><span class="name"> 1072alpha.nondeterminism.PointerIteration</span><span class="lang"> 1073(C++)</span><div class="descr"> 1074Check for non-determinism caused by iterating unordered containers of pointers.</div></div></a></td> 1075<td><div class="exampleContainer expandable"> 1076<div class="example"><pre> 1077// C++ 1078void test() { 1079 int a = 1, b = 2; 1080 std::unordered_set<int *> UnorderedPtrSet = {&a, &b}; 1081 1082 for (auto i : UnorderedPtrSet) // warn 1083 f(i); 1084} 1085</pre></div></div></td></tr> 1086<tr><td><a id="alpha.nondeterminism.PointerSorting"><div class="namedescr expandable"><span class="name"> 1087alpha.nondeterminism.PointerSorting</span><span class="lang"> 1088(C++)</span><div class="descr"> 1089Check for non-determinism caused by sorting of pointers.</div></div></a></td> 1090<td><div class="exampleContainer expandable"> 1091<div class="example"><pre> 1092// C++ 1093void test() { 1094 int a = 1, b = 2; 1095 std::vector<int *> V = {&a, &b}; 1096 std::sort(V.begin(), V.end()); // warn 1097} 1098</pre></div></div></td></tr> 1099</tbody></table> 1100 1101</div> <!-- page --> 1102</div> <!-- content --> 1103</body> 1104</html> 1105