1*67e74705SXin Li<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 2*67e74705SXin Li "http://www.w3.org/TR/html4/strict.dtd"> 3*67e74705SXin Li<html> 4*67e74705SXin Li<head> 5*67e74705SXin Li <title>Alpha Checks</title> 6*67e74705SXin Li <link type="text/css" rel="stylesheet" href="menu.css"> 7*67e74705SXin Li <link type="text/css" rel="stylesheet" href="content.css"> 8*67e74705SXin Li <script type="text/javascript" src="scripts/menu.js"></script> 9*67e74705SXin Li <script type="text/javascript" src="scripts/expandcollapse.js"></script> 10*67e74705SXin Li <style type="text/css"> 11*67e74705SXin Li tr:first-child { width:20%; } 12*67e74705SXin Li </style> 13*67e74705SXin Li</head> 14*67e74705SXin Li<body onload="initExpandCollapse()"> 15*67e74705SXin Li 16*67e74705SXin Li<div id="page"> 17*67e74705SXin Li<!--#include virtual="menu.html.incl"--> 18*67e74705SXin Li 19*67e74705SXin Li<div id="content"> 20*67e74705SXin Li<h1>Alpha Checkers</h1> 21*67e74705SXin LiExperimental checkers in addition to the <a href = "available_checks.html"> 22*67e74705SXin LiDefault Checkers</a>. These are checkers with known issues or limitations that 23*67e74705SXin Likeep them from being on by default. They are likely to have false positives. 24*67e74705SXin LiBug reports are welcome but will likely not be investigated for some time. 25*67e74705SXin LiPatches welcome! 26*67e74705SXin Li<ul> 27*67e74705SXin Li<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li> 28*67e74705SXin Li<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li> 29*67e74705SXin Li<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li> 30*67e74705SXin Li<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li> 31*67e74705SXin Li<li><a href="#security_alpha_checkers">Security Alpha Checkers</a></li> 32*67e74705SXin Li<li><a href="#unix_alpha_checkers">Unix Alpha Checkers</a></li> 33*67e74705SXin Li</ul> 34*67e74705SXin Li 35*67e74705SXin Li<!------------------------------ core alpha -----------------------------------> 36*67e74705SXin Li<h3 id="core_alpha_checkers">Core Alpha Checkers</h3> 37*67e74705SXin Li<table class="checkers"> 38*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 39*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 40*67e74705SXin Li 41*67e74705SXin Li<tbody> 42*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 43*67e74705SXin Lialpha.core.BoolAssignment</span><span class="lang"> 44*67e74705SXin Li(ObjC)</span><div class="descr"> 45*67e74705SXin LiWarn about assigning non-{0,1} values to boolean variables.</div></div></td> 46*67e74705SXin Li<td><div class="exampleContainer expandable"> 47*67e74705SXin Li<div class="example"><pre> 48*67e74705SXin Livoid test() { 49*67e74705SXin Li BOOL b = -1; // warn 50*67e74705SXin Li} 51*67e74705SXin Li</pre></div></div></td></tr> 52*67e74705SXin Li 53*67e74705SXin Li 54*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 55*67e74705SXin Lialpha.core.CastSize</span><span class="lang"> 56*67e74705SXin Li(C)</span><div class="descr"> 57*67e74705SXin LiCheck when casting a malloc'ed type T, whether the size is a multiple of the 58*67e74705SXin Lisize of T (Works only with <span class="name">unix.Malloc</span> 59*67e74705SXin Lior <span class="name">alpha.unix.MallocWithAnnotations</span> 60*67e74705SXin Lichecks enabled).</div></div></td> 61*67e74705SXin Li<td><div class="exampleContainer expandable"> 62*67e74705SXin Li<div class="example"><pre> 63*67e74705SXin Livoid test() { 64*67e74705SXin Li int *x = (int *)malloc(11); // warn 65*67e74705SXin Li} 66*67e74705SXin Li</pre></div></div></td></tr> 67*67e74705SXin Li 68*67e74705SXin Li 69*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 70*67e74705SXin Lialpha.core.CastToStruct</span><span class="lang"> 71*67e74705SXin Li(C, C++)</span><div class="descr"> 72*67e74705SXin LiCheck for cast from non-struct pointer to struct pointer.</div></div></td> 73*67e74705SXin Li<td><div class="exampleContainer expandable"> 74*67e74705SXin Li<div class="example"><pre> 75*67e74705SXin Li// C 76*67e74705SXin Listruct s {}; 77*67e74705SXin Li 78*67e74705SXin Livoid test(int *p) { 79*67e74705SXin Li struct s *ps = (struct s *) p; // warn 80*67e74705SXin Li} 81*67e74705SXin Li</pre></div><div class="separator"></div> 82*67e74705SXin Li<div class="example"><pre> 83*67e74705SXin Li// C++ 84*67e74705SXin Liclass c {}; 85*67e74705SXin Li 86*67e74705SXin Livoid test(int *p) { 87*67e74705SXin Li c *pc = (c *) p; // warn 88*67e74705SXin Li} 89*67e74705SXin Li</pre></div></div></td></tr> 90*67e74705SXin Li 91*67e74705SXin Li 92*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 93*67e74705SXin Lialpha.core.FixedAddr</span><span class="lang"> 94*67e74705SXin Li(C)</span><div class="descr"> 95*67e74705SXin LiCheck for assignment of a fixed address to a pointer.</div></div></td> 96*67e74705SXin Li<td><div class="exampleContainer expandable"> 97*67e74705SXin Li<div class="example"><pre> 98*67e74705SXin Livoid test() { 99*67e74705SXin Li int *p; 100*67e74705SXin Li p = (int *) 0x10000; // warn 101*67e74705SXin Li} 102*67e74705SXin Li</pre></div></div></td></tr> 103*67e74705SXin Li 104*67e74705SXin Li 105*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 106*67e74705SXin Lialpha.core.IdenticalExpr</span><span class="lang"> 107*67e74705SXin Li(C, C++)</span><div class="descr"> 108*67e74705SXin LiWarn about suspicious uses of identical expressions.</div></div></td> 109*67e74705SXin Li<td><div class="exampleContainer expandable"> 110*67e74705SXin Li<div class="example"><pre> 111*67e74705SXin Li// C 112*67e74705SXin Livoid test() { 113*67e74705SXin Li int a = 5; 114*67e74705SXin Li int b = a | 4 | a; // warn: identical expr on both sides 115*67e74705SXin Li} 116*67e74705SXin Li</pre></div><div class="separator"></div> 117*67e74705SXin Li<div class="example"><pre> 118*67e74705SXin Li// C++ 119*67e74705SXin Libool f(void); 120*67e74705SXin Li 121*67e74705SXin Livoid test(bool b) { 122*67e74705SXin Li int i = 10; 123*67e74705SXin Li if (f()) { // warn: true and false branches are identical 124*67e74705SXin Li do { 125*67e74705SXin Li i--; 126*67e74705SXin Li } while (f()); 127*67e74705SXin Li } else { 128*67e74705SXin Li do { 129*67e74705SXin Li i--; 130*67e74705SXin Li } while (f()); 131*67e74705SXin Li } 132*67e74705SXin Li} 133*67e74705SXin Li</pre></div></div></td></tr> 134*67e74705SXin Li 135*67e74705SXin Li 136*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 137*67e74705SXin Lialpha.core.PointerArithm</span><span class="lang"> 138*67e74705SXin Li(C)</span><div class="descr"> 139*67e74705SXin LiCheck for pointer arithmetic on locations other than array 140*67e74705SXin Lielements.</div></div></td> 141*67e74705SXin Li<td><div class="exampleContainer expandable"> 142*67e74705SXin Li<div class="example"><pre> 143*67e74705SXin Livoid test() { 144*67e74705SXin Li int x; 145*67e74705SXin Li int *p; 146*67e74705SXin Li p = &x + 1; // warn 147*67e74705SXin Li} 148*67e74705SXin Li</pre></div></div></td></tr> 149*67e74705SXin Li 150*67e74705SXin Li 151*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 152*67e74705SXin Lialpha.core.PointerSub</span><span class="lang"> 153*67e74705SXin Li(C)</span><div class="descr"> 154*67e74705SXin LiCheck for pointer subtractions on two pointers pointing to different memory 155*67e74705SXin Lichunks.</div></div></td> 156*67e74705SXin Li<td><div class="exampleContainer expandable"> 157*67e74705SXin Li<div class="example"><pre> 158*67e74705SXin Livoid test() { 159*67e74705SXin Li int x, y; 160*67e74705SXin Li int d = &y - &x; // warn 161*67e74705SXin Li} 162*67e74705SXin Li</pre></div></div></td></tr> 163*67e74705SXin Li 164*67e74705SXin Li 165*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 166*67e74705SXin Lialpha.core.SizeofPtr</span><span class="lang"> 167*67e74705SXin Li(C)</span><div class="descr"> 168*67e74705SXin LiWarn about unintended use of <code>sizeof()</code> on pointer 169*67e74705SXin Liexpressions.</div></div></td> 170*67e74705SXin Li<td><div class="exampleContainer expandable"> 171*67e74705SXin Li<div class="example"><pre> 172*67e74705SXin Listruct s {}; 173*67e74705SXin Li 174*67e74705SXin Liint test(struct s *p) { 175*67e74705SXin Li return sizeof(p); 176*67e74705SXin Li // warn: sizeof(ptr) can produce an unexpected result 177*67e74705SXin Li} 178*67e74705SXin Li</pre></div></div></td></tr> 179*67e74705SXin Li 180*67e74705SXin Li</tbody></table> 181*67e74705SXin Li 182*67e74705SXin Li<!--------------------------- cplusplus alpha ---------------------------------> 183*67e74705SXin Li<h3 id="cplusplus_alpha_checkers">C++ Alpha Checkers</h3> 184*67e74705SXin Li<table class="checkers"> 185*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 186*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 187*67e74705SXin Li 188*67e74705SXin Li<tbody> 189*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 190*67e74705SXin Lialpha.cplusplus.NewDeleteLeaks</span><span class="lang"> 191*67e74705SXin Li(C++)</span><div class="descr"> 192*67e74705SXin LiCheck for memory leaks. Traces memory managed by <code>new</code>/<code> 193*67e74705SXin Lidelete</code>.</div></div></td> 194*67e74705SXin Li<td><div class="exampleContainer expandable"> 195*67e74705SXin Li<div class="example"><pre> 196*67e74705SXin Livoid test() { 197*67e74705SXin Li int *p = new int; 198*67e74705SXin Li} // warn 199*67e74705SXin Li</pre></div></div></td></tr> 200*67e74705SXin Li 201*67e74705SXin Li 202*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 203*67e74705SXin Lialpha.cplusplus.VirtualCall</span><span class="lang"> 204*67e74705SXin Li(C++)</span><div class="descr"> 205*67e74705SXin LiCheck virtual member function calls during construction or 206*67e74705SXin Lidestruction.</div></div></td> 207*67e74705SXin Li<td><div class="exampleContainer expandable"> 208*67e74705SXin Li<div class="example"><pre> 209*67e74705SXin Liclass A { 210*67e74705SXin Lipublic: 211*67e74705SXin Li A() { 212*67e74705SXin Li f(); // warn 213*67e74705SXin Li } 214*67e74705SXin Li virtual void f(); 215*67e74705SXin Li}; 216*67e74705SXin Li</pre></div><div class="separator"></div> 217*67e74705SXin Li<div class="example"><pre> 218*67e74705SXin Liclass A { 219*67e74705SXin Lipublic: 220*67e74705SXin Li ~A() { 221*67e74705SXin Li this->f(); // warn 222*67e74705SXin Li } 223*67e74705SXin Li virtual void f(); 224*67e74705SXin Li}; 225*67e74705SXin Li</pre></div></div></td></tr> 226*67e74705SXin Li 227*67e74705SXin Li</tbody></table> 228*67e74705SXin Li 229*67e74705SXin Li<!--------------------------- dead code alpha ---------------------------------> 230*67e74705SXin Li<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3> 231*67e74705SXin Li<table class="checkers"> 232*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 233*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 234*67e74705SXin Li 235*67e74705SXin Li<tbody> 236*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 237*67e74705SXin Lialpha.deadcode.UnreachableCode</span><span class="lang"> 238*67e74705SXin Li(C, C++, ObjC)</span><div class="descr"> 239*67e74705SXin LiCheck unreachable code.</div></div></td> 240*67e74705SXin Li<td><div class="exampleContainer expandable"> 241*67e74705SXin Li<div class="example"><pre> 242*67e74705SXin Li// C 243*67e74705SXin Liint test() { 244*67e74705SXin Li int x = 1; 245*67e74705SXin Li while(x); 246*67e74705SXin Li return x; // warn 247*67e74705SXin Li} 248*67e74705SXin Li</pre></div><div class="separator"></div> 249*67e74705SXin Li<div class="example"><pre> 250*67e74705SXin Li// C++ 251*67e74705SXin Livoid test() { 252*67e74705SXin Li int a = 2; 253*67e74705SXin Li 254*67e74705SXin Li while (a > 1) 255*67e74705SXin Li a--; 256*67e74705SXin Li 257*67e74705SXin Li if (a > 1) 258*67e74705SXin Li a++; // warn 259*67e74705SXin Li} 260*67e74705SXin Li</pre></div><div class="separator"></div> 261*67e74705SXin Li<div class="example"><pre> 262*67e74705SXin Li// Objective-C 263*67e74705SXin Livoid test(id x) { 264*67e74705SXin Li return; 265*67e74705SXin Li [x retain]; // warn 266*67e74705SXin Li} 267*67e74705SXin Li</pre></div></div></td></tr> 268*67e74705SXin Li</tbody></table> 269*67e74705SXin Li 270*67e74705SXin Li<!---------------------------- OS X alpha --------------------------------------> 271*67e74705SXin Li<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3> 272*67e74705SXin Li<table class="checkers"> 273*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 274*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 275*67e74705SXin Li 276*67e74705SXin Li<tbody> 277*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 278*67e74705SXin Lialpha.osx.cocoa.Dealloc</span><span class="lang"> 279*67e74705SXin Li(ObjC)</span><div class="descr"> 280*67e74705SXin LiWarn about Objective-C classes that lack a correct implementation 281*67e74705SXin Liof <code>-dealloc</code>. 282*67e74705SXin Li</div></div></td> 283*67e74705SXin Li<td><div class="exampleContainer expandable"> 284*67e74705SXin Li<div class="example"><pre> 285*67e74705SXin Li@interface MyObject : NSObject { 286*67e74705SXin Li id _myproperty; 287*67e74705SXin Li} 288*67e74705SXin Li@end 289*67e74705SXin Li 290*67e74705SXin Li@implementation MyObject // warn: lacks 'dealloc' 291*67e74705SXin Li@end 292*67e74705SXin Li</pre></div><div class="separator"></div> 293*67e74705SXin Li<div class="example"><pre> 294*67e74705SXin Li@interface MyObject : NSObject {} 295*67e74705SXin Li@property(assign) id myproperty; 296*67e74705SXin Li@end 297*67e74705SXin Li 298*67e74705SXin Li@implementation MyObject // warn: does not send 'dealloc' to super 299*67e74705SXin Li- (void)dealloc { 300*67e74705SXin Li self.myproperty = 0; 301*67e74705SXin Li} 302*67e74705SXin Li@end 303*67e74705SXin Li</pre></div><div class="separator"></div> 304*67e74705SXin Li<div class="example"><pre> 305*67e74705SXin Li@interface MyObject : NSObject { 306*67e74705SXin Li id _myproperty; 307*67e74705SXin Li} 308*67e74705SXin Li@property(retain) id myproperty; 309*67e74705SXin Li@end 310*67e74705SXin Li 311*67e74705SXin Li@implementation MyObject 312*67e74705SXin Li@synthesize myproperty = _myproperty; 313*67e74705SXin Li // warn: var was retained but wasn't released 314*67e74705SXin Li- (void)dealloc { 315*67e74705SXin Li [super dealloc]; 316*67e74705SXin Li} 317*67e74705SXin Li@end 318*67e74705SXin Li</pre></div><div class="separator"></div> 319*67e74705SXin Li<div class="example"><pre> 320*67e74705SXin Li@interface MyObject : NSObject { 321*67e74705SXin Li id _myproperty; 322*67e74705SXin Li} 323*67e74705SXin Li@property(assign) id myproperty; 324*67e74705SXin Li@end 325*67e74705SXin Li 326*67e74705SXin Li@implementation MyObject 327*67e74705SXin Li@synthesize myproperty = _myproperty; 328*67e74705SXin Li // warn: var wasn't retained but was released 329*67e74705SXin Li- (void)dealloc { 330*67e74705SXin Li [_myproperty release]; 331*67e74705SXin Li [super dealloc]; 332*67e74705SXin Li} 333*67e74705SXin Li@end 334*67e74705SXin Li</pre></div></div></td></tr> 335*67e74705SXin Li 336*67e74705SXin Li 337*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 338*67e74705SXin Lialpha.osx.cocoa.DirectIvarAssignment</span><span class="lang"> 339*67e74705SXin Li(ObjC)</span><div class="descr"> 340*67e74705SXin LiCheck that Objective C properties follow the following rule: the property 341*67e74705SXin Lishould be set with the setter, not though a direct assignment.</div></div></td> 342*67e74705SXin Li<td><div class="exampleContainer expandable"> 343*67e74705SXin Li<div class="example"><pre> 344*67e74705SXin Li@interface MyClass : NSObject {} 345*67e74705SXin Li@property (readonly) id A; 346*67e74705SXin Li- (void) foo; 347*67e74705SXin Li@end 348*67e74705SXin Li 349*67e74705SXin Li@implementation MyClass 350*67e74705SXin Li- (void) foo { 351*67e74705SXin Li _A = 0; // warn 352*67e74705SXin Li} 353*67e74705SXin Li@end 354*67e74705SXin Li</pre></div></div></td></tr> 355*67e74705SXin Li 356*67e74705SXin Li 357*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 358*67e74705SXin Lialpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions</span><span class="lang"> 359*67e74705SXin Li(ObjC)</span><div class="descr"> 360*67e74705SXin LiCheck for direct assignments to instance variables in the methods annotated 361*67e74705SXin Liwith <code>objc_no_direct_instance_variable_assignment</code>.</div></div></td> 362*67e74705SXin Li<td><div class="exampleContainer expandable"> 363*67e74705SXin Li<div class="example"><pre> 364*67e74705SXin Li@interface MyClass : NSObject {} 365*67e74705SXin Li@property (readonly) id A; 366*67e74705SXin Li- (void) fAnnotated __attribute__(( 367*67e74705SXin Li annotate("objc_no_direct_instance_variable_assignment"))); 368*67e74705SXin Li- (void) fNotAnnotated; 369*67e74705SXin Li@end 370*67e74705SXin Li 371*67e74705SXin Li@implementation MyClass 372*67e74705SXin Li- (void) fAnnotated { 373*67e74705SXin Li _A = 0; // warn 374*67e74705SXin Li} 375*67e74705SXin Li- (void) fNotAnnotated { 376*67e74705SXin Li _A = 0; // no warn 377*67e74705SXin Li} 378*67e74705SXin Li@end 379*67e74705SXin Li</pre></div></div></td></tr> 380*67e74705SXin Li 381*67e74705SXin Li 382*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 383*67e74705SXin Lialpha.osx.cocoa.InstanceVariableInvalidation</span><span class="lang"> 384*67e74705SXin Li(ObjC)</span><div class="descr"> 385*67e74705SXin LiCheck that the invalidatable instance variables are invalidated in the methods 386*67e74705SXin Liannotated with <code>objc_instance_variable_invalidator</code>.</div></div></td> 387*67e74705SXin Li<td><div class="exampleContainer expandable"> 388*67e74705SXin Li<div class="example"><pre> 389*67e74705SXin Li@protocol Invalidation <NSObject> 390*67e74705SXin Li- (void) invalidate 391*67e74705SXin Li __attribute__((annotate("objc_instance_variable_invalidator"))); 392*67e74705SXin Li@end 393*67e74705SXin Li 394*67e74705SXin Li@interface InvalidationImpObj : NSObject <Invalidation> 395*67e74705SXin Li@end 396*67e74705SXin Li 397*67e74705SXin Li@interface SubclassInvalidationImpObj : InvalidationImpObj { 398*67e74705SXin Li InvalidationImpObj *var; 399*67e74705SXin Li} 400*67e74705SXin Li- (void)invalidate; 401*67e74705SXin Li@end 402*67e74705SXin Li 403*67e74705SXin Li@implementation SubclassInvalidationImpObj 404*67e74705SXin Li- (void) invalidate {} 405*67e74705SXin Li@end 406*67e74705SXin Li// warn: var needs to be invalidated or set to nil 407*67e74705SXin Li</pre></div></div></td></tr> 408*67e74705SXin Li 409*67e74705SXin Li 410*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 411*67e74705SXin Lialpha.osx.cocoa.MissingInvalidationMethod</span><span class="lang"> 412*67e74705SXin Li(ObjC)</span><div class="descr"> 413*67e74705SXin LiCheck that the invalidation methods are present in classes that contain 414*67e74705SXin Liinvalidatable instance variables.</div></div></td> 415*67e74705SXin Li<td><div class="exampleContainer expandable"> 416*67e74705SXin Li<div class="example"><pre> 417*67e74705SXin Li@protocol Invalidation <NSObject> 418*67e74705SXin Li- (void)invalidate 419*67e74705SXin Li __attribute__((annotate("objc_instance_variable_invalidator"))); 420*67e74705SXin Li@end 421*67e74705SXin Li 422*67e74705SXin Li@interface NeedInvalidation : NSObject <Invalidation> 423*67e74705SXin Li@end 424*67e74705SXin Li 425*67e74705SXin Li@interface MissingInvalidationMethodDecl : NSObject { 426*67e74705SXin Li NeedInvalidation *Var; // warn 427*67e74705SXin Li} 428*67e74705SXin Li@end 429*67e74705SXin Li 430*67e74705SXin Li@implementation MissingInvalidationMethodDecl 431*67e74705SXin Li@end 432*67e74705SXin Li</pre></div></div></td></tr> 433*67e74705SXin Li 434*67e74705SXin Li</tbody></table> 435*67e74705SXin Li 436*67e74705SXin Li<!------------------------- security alpha ------------------------------------> 437*67e74705SXin Li<h3 id="security_alpha_checkers">Security Alpha Checkers</h3> 438*67e74705SXin Li<table class="checkers"> 439*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 440*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 441*67e74705SXin Li 442*67e74705SXin Li<tbody> 443*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 444*67e74705SXin Lialpha.security.ArrayBound</span><span class="lang"> 445*67e74705SXin Li(C)</span><div class="descr"> 446*67e74705SXin LiWarn about buffer overflows (older checker).</div></div></td> 447*67e74705SXin Li<td><div class="exampleContainer expandable"> 448*67e74705SXin Li<div class="example"><pre> 449*67e74705SXin Livoid test() { 450*67e74705SXin Li char *s = ""; 451*67e74705SXin Li char c = s[1]; // warn 452*67e74705SXin Li} 453*67e74705SXin Li</pre></div><div class="separator"></div> 454*67e74705SXin Li<div class="example"><pre> 455*67e74705SXin Listruct seven_words { 456*67e74705SXin Li int c[7]; 457*67e74705SXin Li}; 458*67e74705SXin Li 459*67e74705SXin Livoid test() { 460*67e74705SXin Li struct seven_words a, *p; 461*67e74705SXin Li p = &a; 462*67e74705SXin Li p[0] = a; 463*67e74705SXin Li p[1] = a; 464*67e74705SXin Li p[2] = a; // warn 465*67e74705SXin Li} 466*67e74705SXin Li</pre></div><div class="separator"></div> 467*67e74705SXin Li<div class="example"><pre> 468*67e74705SXin Li// note: requires unix.Malloc or 469*67e74705SXin Li// alpha.unix.MallocWithAnnotations checks enabled. 470*67e74705SXin Livoid test() { 471*67e74705SXin Li int *p = malloc(12); 472*67e74705SXin Li p[3] = 4; // warn 473*67e74705SXin Li} 474*67e74705SXin Li</pre></div><div class="separator"></div> 475*67e74705SXin Li<div class="example"><pre> 476*67e74705SXin Livoid test() { 477*67e74705SXin Li char a[2]; 478*67e74705SXin Li int *b = (int*)a; 479*67e74705SXin Li b[1] = 3; // warn 480*67e74705SXin Li} 481*67e74705SXin Li</pre></div></div></td></tr> 482*67e74705SXin Li 483*67e74705SXin Li 484*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 485*67e74705SXin Lialpha.security.ArrayBoundV2</span><span class="lang"> 486*67e74705SXin Li(C)</span><div class="descr"> 487*67e74705SXin LiWarn about buffer overflows (newer checker).</div></div></td> 488*67e74705SXin Li<td><div class="exampleContainer expandable"> 489*67e74705SXin Li<div class="example"><pre> 490*67e74705SXin Livoid test() { 491*67e74705SXin Li char *s = ""; 492*67e74705SXin Li char c = s[1]; // warn 493*67e74705SXin Li} 494*67e74705SXin Li</pre></div><div class="separator"></div> 495*67e74705SXin Li<div class="example"><pre> 496*67e74705SXin Livoid test() { 497*67e74705SXin Li int buf[100]; 498*67e74705SXin Li int *p = buf; 499*67e74705SXin Li p = p + 99; 500*67e74705SXin Li p[1] = 1; // warn 501*67e74705SXin Li} 502*67e74705SXin Li</pre></div><div class="separator"></div> 503*67e74705SXin Li<div class="example"><pre> 504*67e74705SXin Li// note: compiler has internal check for this. 505*67e74705SXin Li// Use -Wno-array-bounds to suppress compiler warning. 506*67e74705SXin Livoid test() { 507*67e74705SXin Li int buf[100][100]; 508*67e74705SXin Li buf[0][-1] = 1; // warn 509*67e74705SXin Li} 510*67e74705SXin Li</pre></div><div class="separator"></div> 511*67e74705SXin Li<div class="example"><pre> 512*67e74705SXin Li// note: requires alpha.security.taint check turned on. 513*67e74705SXin Livoid test() { 514*67e74705SXin Li char s[] = "abc"; 515*67e74705SXin Li int x = getchar(); 516*67e74705SXin Li char c = s[x]; // warn: index is tainted 517*67e74705SXin Li} 518*67e74705SXin Li</pre></div></div></td></tr> 519*67e74705SXin Li 520*67e74705SXin Li 521*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 522*67e74705SXin Lialpha.security.MallocOverflow</span><span class="lang"> 523*67e74705SXin Li(C)</span><div class="descr"> 524*67e74705SXin LiCheck for overflows in the arguments to <code>malloc()</code>.</div></div></td> 525*67e74705SXin Li<td><div class="exampleContainer expandable"> 526*67e74705SXin Li<div class="example"><pre> 527*67e74705SXin Livoid test(int n) { 528*67e74705SXin Li void *p = malloc(n * sizeof(int)); // warn 529*67e74705SXin Li} 530*67e74705SXin Li</pre></div></div></td></tr> 531*67e74705SXin Li 532*67e74705SXin Li 533*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 534*67e74705SXin Lialpha.security.ReturnPtrRange</span><span class="lang"> 535*67e74705SXin Li(C)</span><div class="descr"> 536*67e74705SXin LiCheck for an out-of-bound pointer being returned to callers.</div></div></td> 537*67e74705SXin Li<td><div class="exampleContainer expandable"> 538*67e74705SXin Li<div class="example"><pre> 539*67e74705SXin Listatic int A[10]; 540*67e74705SXin Li 541*67e74705SXin Liint *test() { 542*67e74705SXin Li int *p = A + 10; 543*67e74705SXin Li return p; // warn 544*67e74705SXin Li} 545*67e74705SXin Li</pre></div><div class="separator"></div> 546*67e74705SXin Li<div class="example"><pre> 547*67e74705SXin Liint test(void) { 548*67e74705SXin Li int x; 549*67e74705SXin Li return x; // warn: undefined or garbage returned 550*67e74705SXin Li} 551*67e74705SXin Li</pre></div></div></td></tr> 552*67e74705SXin Li 553*67e74705SXin Li 554*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 555*67e74705SXin Lialpha.security.taint.TaintPropagation</span><span class="lang"> 556*67e74705SXin Li(C)</span><div class="descr"> 557*67e74705SXin LiGenerate taint information used by other checkers.</div></div></td> 558*67e74705SXin Li<td><div class="exampleContainer expandable"> 559*67e74705SXin Li<div class="example"><pre> 560*67e74705SXin Livoid test() { 561*67e74705SXin Li char x = getchar(); // 'x' marked as tainted 562*67e74705SXin Li system(&x); // warn: untrusted data is passed to a system call 563*67e74705SXin Li} 564*67e74705SXin Li</pre></div><div class="separator"></div> 565*67e74705SXin Li<div class="example"><pre> 566*67e74705SXin Li// note: compiler internally checks if the second param to 567*67e74705SXin Li// sprintf is a string literal or not. 568*67e74705SXin Li// Use -Wno-format-security to suppress compiler warning. 569*67e74705SXin Livoid test() { 570*67e74705SXin Li char s[10], buf[10]; 571*67e74705SXin Li fscanf(stdin, "%s", s); // 's' marked as tainted 572*67e74705SXin Li 573*67e74705SXin Li sprintf(buf, s); // warn: untrusted data as a format string 574*67e74705SXin Li} 575*67e74705SXin Li</pre></div><div class="separator"></div> 576*67e74705SXin Li<div class="example"><pre> 577*67e74705SXin Livoid test() { 578*67e74705SXin Li size_t ts; 579*67e74705SXin Li scanf("%zd", &ts); // 'ts' marked as tainted 580*67e74705SXin Li int *p = (int *)malloc(ts * sizeof(int)); 581*67e74705SXin Li // warn: untrusted data as bufer size 582*67e74705SXin Li} 583*67e74705SXin Li</pre></div></div></td></tr> 584*67e74705SXin Li 585*67e74705SXin Li</tbody></table> 586*67e74705SXin Li 587*67e74705SXin Li<!--------------------------- unix alpha --------------------------------------> 588*67e74705SXin Li<h3 id="unix_alpha_checkers">Unix Alpha Checkers</h3> 589*67e74705SXin Li<table class="checkers"> 590*67e74705SXin Li<colgroup><col class="namedescr"><col class="example"></colgroup> 591*67e74705SXin Li<thead><tr><td>Name, Description</td><td>Example</td></tr></thead> 592*67e74705SXin Li 593*67e74705SXin Li<tbody> 594*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 595*67e74705SXin Lialpha.unix.Chroot</span><span class="lang"> 596*67e74705SXin Li(C)</span><div class="descr"> 597*67e74705SXin LiCheck improper use of <code>chroot</code>.</div></div></td> 598*67e74705SXin Li<td><div class="exampleContainer expandable"> 599*67e74705SXin Li<div class="example"><pre> 600*67e74705SXin Livoid f(); 601*67e74705SXin Li 602*67e74705SXin Livoid test() { 603*67e74705SXin Li chroot("/usr/local"); 604*67e74705SXin Li f(); // warn: no call of chdir("/") immediately after chroot 605*67e74705SXin Li} 606*67e74705SXin Li</pre></div></div></td></tr> 607*67e74705SXin Li 608*67e74705SXin Li 609*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 610*67e74705SXin Lialpha.unix.MallocWithAnnotations</span><span class="lang"> 611*67e74705SXin Li(C)</span><div class="descr"> 612*67e74705SXin LiCheck for memory leaks, double free, and use-after-free problems. Assumes that 613*67e74705SXin Liall user-defined functions which might free a pointer are 614*67e74705SXin Liannotated.</div></div></td> 615*67e74705SXin Li<td><div class="exampleContainer expandable"> 616*67e74705SXin Li<div class="example"><pre> 617*67e74705SXin Livoid __attribute((ownership_returns(malloc))) *my_malloc(size_t); 618*67e74705SXin Li 619*67e74705SXin Livoid test() { 620*67e74705SXin Li int *p = my_malloc(1); 621*67e74705SXin Li} // warn: potential leak 622*67e74705SXin Li</pre></div><div class="separator"></div> 623*67e74705SXin Li<div class="example"><pre> 624*67e74705SXin Livoid __attribute((ownership_returns(malloc))) *my_malloc(size_t); 625*67e74705SXin Livoid __attribute((ownership_takes(malloc, 1))) my_free(void *); 626*67e74705SXin Li 627*67e74705SXin Livoid test() { 628*67e74705SXin Li int *p = my_malloc(1); 629*67e74705SXin Li my_free(p); 630*67e74705SXin Li my_free(p); // warn: attempt to free released 631*67e74705SXin Li} 632*67e74705SXin Li</pre></div><div class="separator"></div> 633*67e74705SXin Li<div class="example"><pre> 634*67e74705SXin Livoid __attribute((ownership_returns(malloc))) *my_malloc(size_t); 635*67e74705SXin Livoid __attribute((ownership_holds(malloc, 1))) my_hold(void *); 636*67e74705SXin Li 637*67e74705SXin Livoid test() { 638*67e74705SXin Li int *p = my_malloc(1); 639*67e74705SXin Li my_hold(p); 640*67e74705SXin Li free(p); // warn: attempt to free non-owned memory 641*67e74705SXin Li} 642*67e74705SXin Li</pre></div><div class="separator"></div> 643*67e74705SXin Li<div class="example"><pre> 644*67e74705SXin Livoid __attribute((ownership_takes(malloc, 1))) my_free(void *); 645*67e74705SXin Li 646*67e74705SXin Livoid test() { 647*67e74705SXin Li int *p = malloc(1); 648*67e74705SXin Li my_free(p); 649*67e74705SXin Li *p = 1; // warn: use after free 650*67e74705SXin Li} 651*67e74705SXin Li</pre></div></div></td></tr> 652*67e74705SXin Li 653*67e74705SXin Li 654*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 655*67e74705SXin Lialpha.unix.PthreadLock</span><span class="lang"> 656*67e74705SXin Li(C)</span><div class="descr"> 657*67e74705SXin LiSimple lock -> unlock checker; applies to:<div class=functions> 658*67e74705SXin Lipthread_mutex_lock<br> 659*67e74705SXin Lipthread_rwlock_rdlock<br> 660*67e74705SXin Lipthread_rwlock_wrlock<br> 661*67e74705SXin Lilck_mtx_lock<br> 662*67e74705SXin Lilck_rw_lock_exclusive<br> 663*67e74705SXin Lilck_rw_lock_shared<br> 664*67e74705SXin Lipthread_mutex_trylock<br> 665*67e74705SXin Lipthread_rwlock_tryrdlock<br> 666*67e74705SXin Lipthread_rwlock_tryrwlock<br> 667*67e74705SXin Lilck_mtx_try_lock<br> 668*67e74705SXin Lilck_rw_try_lock_exclusive<br> 669*67e74705SXin Lilck_rw_try_lock_shared<br> 670*67e74705SXin Lipthread_mutex_unlock<br> 671*67e74705SXin Lipthread_rwlock_unlock<br> 672*67e74705SXin Lilck_mtx_unlock<br> 673*67e74705SXin Lilck_rw_done</div></div></div></td> 674*67e74705SXin Li<td><div class="exampleContainer expandable"> 675*67e74705SXin Li<div class="example"><pre> 676*67e74705SXin Lipthread_mutex_t mtx; 677*67e74705SXin Li 678*67e74705SXin Livoid test() { 679*67e74705SXin Li pthread_mutex_lock(&mtx); 680*67e74705SXin Li pthread_mutex_lock(&mtx); 681*67e74705SXin Li // warn: this lock has already been acquired 682*67e74705SXin Li} 683*67e74705SXin Li</pre></div><div class="separator"></div> 684*67e74705SXin Li<div class="example"><pre> 685*67e74705SXin Lilck_mtx_t lck1, lck2; 686*67e74705SXin Li 687*67e74705SXin Livoid test() { 688*67e74705SXin Li lck_mtx_lock(&lck1); 689*67e74705SXin Li lck_mtx_lock(&lck2); 690*67e74705SXin Li lck_mtx_unlock(&lck1); 691*67e74705SXin Li // warn: this was not the most recently acquired lock 692*67e74705SXin Li} 693*67e74705SXin Li</pre></div><div class="separator"></div> 694*67e74705SXin Li<div class="example"><pre> 695*67e74705SXin Lilck_mtx_t lck1, lck2; 696*67e74705SXin Li 697*67e74705SXin Livoid test() { 698*67e74705SXin Li if (lck_mtx_try_lock(&lck1) == 0) 699*67e74705SXin Li return; 700*67e74705SXin Li 701*67e74705SXin Li lck_mtx_lock(&lck2); 702*67e74705SXin Li lck_mtx_unlock(&lck1); 703*67e74705SXin Li // warn: this was not the most recently acquired lock 704*67e74705SXin Li} 705*67e74705SXin Li</pre></div></div></td></tr> 706*67e74705SXin Li 707*67e74705SXin Li 708*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 709*67e74705SXin Lialpha.unix.SimpleStream</span><span class="lang"> 710*67e74705SXin Li(C)</span><div class="descr"> 711*67e74705SXin LiCheck for misuses of stream APIs:<div class=functions> 712*67e74705SXin Lifopen<br> 713*67e74705SXin Lifclose</div>(demo checker, the subject of the demo 714*67e74705SXin Li(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a> 715*67e74705SXin Li,<a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">Video</a>) 716*67e74705SXin Liby Anna Zaks and Jordan Rose presented at the <a href="http://llvm.org/devmtg/2012-11/"> 717*67e74705SXin Li2012 LLVM Developers' Meeting).</a></div></div></td> 718*67e74705SXin Li<td><div class="exampleContainer expandable"> 719*67e74705SXin Li<div class="example"><pre> 720*67e74705SXin Livoid test() { 721*67e74705SXin Li FILE *F = fopen("myfile.txt", "w"); 722*67e74705SXin Li} // warn: opened file is never closed 723*67e74705SXin Li</pre></div><div class="separator"></div> 724*67e74705SXin Li<div class="example"><pre> 725*67e74705SXin Livoid test() { 726*67e74705SXin Li FILE *F = fopen("myfile.txt", "w"); 727*67e74705SXin Li 728*67e74705SXin Li if (F) 729*67e74705SXin Li fclose(F); 730*67e74705SXin Li 731*67e74705SXin Li fclose(F); // warn: closing a previously closed file stream 732*67e74705SXin Li} 733*67e74705SXin Li</pre></div></div></td></tr> 734*67e74705SXin Li 735*67e74705SXin Li 736*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 737*67e74705SXin Lialpha.unix.Stream</span><span class="lang"> 738*67e74705SXin Li(C)</span><div class="descr"> 739*67e74705SXin LiCheck stream handling functions:<div class=functions>fopen<br> 740*67e74705SXin Litmpfile<br> 741*67e74705SXin Lifclose<br> 742*67e74705SXin Lifread<br> 743*67e74705SXin Lifwrite<br> 744*67e74705SXin Lifseek<br> 745*67e74705SXin Liftell<br> 746*67e74705SXin Lirewind<br> 747*67e74705SXin Lifgetpos<br> 748*67e74705SXin Lifsetpos<br> 749*67e74705SXin Liclearerr<br> 750*67e74705SXin Lifeof<br> 751*67e74705SXin Liferror<br> 752*67e74705SXin Lifileno</div></div></div></td> 753*67e74705SXin Li<td><div class="exampleContainer expandable"> 754*67e74705SXin Li<div class="example"><pre> 755*67e74705SXin Livoid test() { 756*67e74705SXin Li FILE *p = fopen("foo", "r"); 757*67e74705SXin Li} // warn: opened file is never closed 758*67e74705SXin Li</pre></div><div class="separator"></div> 759*67e74705SXin Li<div class="example"><pre> 760*67e74705SXin Livoid test() { 761*67e74705SXin Li FILE *p = fopen("foo", "r"); 762*67e74705SXin Li fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL 763*67e74705SXin Li fclose(p); 764*67e74705SXin Li} 765*67e74705SXin Li</pre></div><div class="separator"></div> 766*67e74705SXin Li<div class="example"><pre> 767*67e74705SXin Livoid test() { 768*67e74705SXin Li FILE *p = fopen("foo", "r"); 769*67e74705SXin Li 770*67e74705SXin Li if (p) 771*67e74705SXin Li fseek(p, 1, 3); 772*67e74705SXin Li // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR 773*67e74705SXin Li 774*67e74705SXin Li fclose(p); 775*67e74705SXin Li} 776*67e74705SXin Li</pre></div><div class="separator"></div> 777*67e74705SXin Li<div class="example"><pre> 778*67e74705SXin Livoid test() { 779*67e74705SXin Li FILE *p = fopen("foo", "r"); 780*67e74705SXin Li fclose(p); 781*67e74705SXin Li fclose(p); // warn: already closed 782*67e74705SXin Li} 783*67e74705SXin Li</pre></div><div class="separator"></div> 784*67e74705SXin Li<div class="example"><pre> 785*67e74705SXin Livoid test() { 786*67e74705SXin Li FILE *p = tmpfile(); 787*67e74705SXin Li ftell(p); // warn: stream pointer might be NULL 788*67e74705SXin Li fclose(p); 789*67e74705SXin Li} 790*67e74705SXin Li</pre></div></div></td></tr> 791*67e74705SXin Li 792*67e74705SXin Li 793*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 794*67e74705SXin Lialpha.unix.cstring.BufferOverlap</span><span class="lang"> 795*67e74705SXin Li(C)</span><div class="descr"> 796*67e74705SXin LiChecks for overlap in two buffer arguments; applies to:<div class=functions> 797*67e74705SXin Limemcpy<br> 798*67e74705SXin Limempcpy</div></div></div></td> 799*67e74705SXin Li<td><div class="exampleContainer expandable"> 800*67e74705SXin Li<div class="example"><pre> 801*67e74705SXin Livoid test() { 802*67e74705SXin Li int a[4] = {0}; 803*67e74705SXin Li memcpy(a + 2, a + 1, 8); // warn 804*67e74705SXin Li} 805*67e74705SXin Li</pre></div></div></td></tr> 806*67e74705SXin Li 807*67e74705SXin Li 808*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 809*67e74705SXin Lialpha.unix.cstring.NotNullTerminated</span><span class="lang"> 810*67e74705SXin Li(C)</span><div class="descr"> 811*67e74705SXin LiCheck for arguments which are not null-terminated strings; applies 812*67e74705SXin Lito:<div class=functions> 813*67e74705SXin Listrlen<br> 814*67e74705SXin Listrnlen<br> 815*67e74705SXin Listrcpy<br> 816*67e74705SXin Listrncpy<br> 817*67e74705SXin Listrcat<br> 818*67e74705SXin Listrncat</div></div></div></td> 819*67e74705SXin Li<td><div class="exampleContainer expandable"> 820*67e74705SXin Li<div class="example"><pre> 821*67e74705SXin Livoid test() { 822*67e74705SXin Li int y = strlen((char *)&test); // warn 823*67e74705SXin Li} 824*67e74705SXin Li</pre></div></div></td></tr> 825*67e74705SXin Li 826*67e74705SXin Li 827*67e74705SXin Li<tr><td><div class="namedescr expandable"><span class="name"> 828*67e74705SXin Lialpha.unix.cstring.OutOfBounds</span><span class="lang"> 829*67e74705SXin Li(C)</span><div class="descr"> 830*67e74705SXin LiCheck for out-of-bounds access in string functions; applies 831*67e74705SXin Lito:<div class=functions> 832*67e74705SXin Listrncopy<br> 833*67e74705SXin Listrncat</div></div></div></td> 834*67e74705SXin Li<td><div class="exampleContainer expandable"> 835*67e74705SXin Li<div class="example"><pre> 836*67e74705SXin Livoid test(char *y) { 837*67e74705SXin Li char x[4]; 838*67e74705SXin Li if (strlen(y) == 4) 839*67e74705SXin Li strncpy(x, y, 5); // warn 840*67e74705SXin Li} 841*67e74705SXin Li</pre></div></div></td></tr> 842*67e74705SXin Li 843*67e74705SXin Li</tbody></table> 844*67e74705SXin Li 845*67e74705SXin Li</div> <!-- page --> 846*67e74705SXin Li</div> <!-- content --> 847*67e74705SXin Li</body> 848*67e74705SXin Li</html> 849