diff options
author | Jordan Rose <jordan_rose@apple.com> | 2014-04-29 00:46:17 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2014-04-29 00:46:17 +0000 |
commit | 0dae3637124de2596d666d0b7df31b11185ee201 (patch) | |
tree | 3e1914016b8735d9531f3da7a4dc5a57b9770c0f /www | |
parent | a172a34fb1b047c946366af60eb7e5da2ac32f4c (diff) |
[analyzer] Clean up the lists of current and potential checkers.
Patch by Anton Yartsev, modified by me.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207478 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'www')
-rw-r--r-- | www/analyzer/available_checks.html | 1400 | ||||
-rw-r--r-- | www/analyzer/content.css | 32 | ||||
-rw-r--r-- | www/analyzer/potential_checkers.html | 2185 |
3 files changed, 2544 insertions, 1073 deletions
diff --git a/www/analyzer/available_checks.html b/www/analyzer/available_checks.html index 8c7d9e987a..1f4625ee94 100644 --- a/www/analyzer/available_checks.html +++ b/www/analyzer/available_checks.html @@ -2,187 +2,30 @@ "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> - <title>Available Checks</title> + <title>Available Checkers</title> <link type="text/css" rel="stylesheet" href="menu.css"> <link type="text/css" rel="stylesheet" href="content.css"> <script type="text/javascript" src="scripts/menu.js"></script> + <script type="text/javascript" src="scripts/expandcollapse.js"></script> <style type="text/css"> tr:first-child { width:20%; } </style> </head> -<body> +<body onload="initExpandCollapse()"> <div id="page"> <!--#include virtual="menu.html.incl"--> <div id="content"> - -<h1>Available Checks</h1> - -<h3>The list of the checks the analyzer performs by default</h3> -<p> -<table border="0" cellpadding="3" cellspacing="3" width="100%"> -<!-- <tr> -<th><h4>Checker Name</h4></th> -<th><h4>Description</h4></th> -</tr>--> -<tr> -<td><b>core.AdjustedReturnValue</b></td><td>Check to see if the return value of a function call is different than the caller expects (e.g., from calls through function pointers).</td> -</tr> -<tr> -<td><b>core.CallAndMessage</b></td><td>Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers).</td> -</tr> -<tr> -<td><b>core.DivideZero</b></td><td>Check for division by zero.</td> -</tr> -<tr> -<td><b>core.NonNullParamChecker</b></td><td>Check for null pointers passed as arguments to a function whose arguments are known to be non-null.</td> -</tr> -<tr> -<td><b>core.NullDereference</b></td><td>Check for dereferences of null pointers.</td> -</tr> -<tr> -<td><b>core.StackAddressEscape</b></td><td>Check that addresses to stack memory do not escape the function.</td> -</tr> -<tr> -<td><b>core.UndefinedBinaryOperatorResult</b></td><td>Check for undefined results of binary operators.</td> -</tr> -<tr> -<td><b>core.VLASize</b></td><td>Check for declarations of VLA of undefined or zero size.</td> -</tr> -<tr> -<td><b>core.builtin.BuiltinFunctions</b></td><td>Evaluate compiler builtin functions (e.g., alloca()).</td> -</tr> -<tr> -<td><b>core.builtin.NoReturnFunctions</b></td><td>Evaluate "panic" functions that are known to not return to the caller.</td> -</tr> -<tr> -<td><b>core.uninitialized.ArraySubscript</b></td><td>Check for uninitialized values used as array subscripts.</td> -</tr> -<tr> -<td><b>core.uninitialized.Assign</b></td><td>Check for assigning uninitialized values.</td> -</tr> -<tr> -<td><b>core.uninitialized.Branch</b></td><td>Check for uninitialized values used as branch conditions.</td> -</tr> -<tr> -<td><b>core.uninitialized.CapturedBlockVariable</b></td><td>Check for blocks that capture uninitialized values.</td> -</tr> -<tr> -<td><b>core.uninitialized.UndefReturn</b></td><td>Check for uninitialized values being returned to the caller.</td> -</tr> -<tr> -<td><b>cplusplus.NewDelete</b></td><td>Check for double-free and use-after-free problems involving C++ <code>delete</code>.</td> -</tr> -<tr> -<td><b>deadcode.DeadStores</b></td><td>Check for values stored to variables that are never read afterwards.</td> -</tr> -<!-- -<tr> -<td><b>deadcode.IdempotentOperations</b></td><td>Warn about idempotent operations.</td> -</tr> ---> -<tr> -<td><b>osx.API</b></td><td>Check for proper uses of various Apple APIs.</td> -</tr> -<tr> -<td><b>osx.SecKeychainAPI</b></td><td>Check for proper uses of Secure Keychain APIs.</td> -</tr> -<tr> -<td><b>osx.cocoa.AtSync</b></td><td>Check for nil pointers used as mutexes for @synchronized.</td> -</tr> -<tr> -<td><b>osx.cocoa.ClassRelease</b></td><td>Check for sending 'retain', 'release', or 'autorelease' directly to a Class.</td> -</tr> -<tr> -<td><b>osx.cocoa.IncompatibleMethodTypes</b></td><td>Warn about Objective-C method signatures with type incompatibilities.</td> -</tr> -<tr> -<td><b>osx.cocoa.NSAutoreleasePool</b></td><td>Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode.</td> -</tr> -<tr> -<td><b>osx.cocoa.NSError</b></td><td>Check usage of NSError** parameters.</td> -</tr> -<tr> -<td><b>osx.cocoa.NilArg</b></td><td>Check for prohibited nil arguments to ObjC method calls.</td> -</tr> -<tr> -<td><b>osx.cocoa.RetainCount</b></td><td>Check for leaks and improper reference count management.</td> -</tr> -<tr> -<td><b>osx.cocoa.SelfInit</b></td><td>Check that 'self' is properly initialized inside an initializer method.</td> -</tr> -<tr> -<td><b>osx.cocoa.UnusedIvars</b></td><td>Warn about private ivars that are never used.</td> -</tr> -<tr> -<td><b>osx.cocoa.VariadicMethodTypes</b></td><td>Check for passing non-Objective-C types to variadic methods that expect only Objective-C types.</td> -</tr> -<tr> -<td><b>osx.coreFoundation.CFError</b></td><td>Check usage of CFErrorRef* parameters.</td> -</tr> -<tr> -<td><b>osx.coreFoundation.CFNumber</b></td><td>Check for proper uses of CFNumberCreate.</td> -</tr> -<tr> -<td><b>osx.coreFoundation.CFRetainRelease</b></td><td>Check for null arguments to CFRetain/CFRelease/CFMakeCollectable.</td> -</tr> -<tr> -<td><b>osx.coreFoundation.containers.OutOfBounds</b></td><td>Checks for index out-of-bounds when using 'CFArray' API.</td> -</tr> -<tr> -<td><b>osx.coreFoundation.containers.PointerSizedValues</b></td><td>Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values.</td> -</tr> -<tr> -<td><b>security.FloatLoopCounter</b></td><td>Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP).</td> -</tr> -<tr> -<td><b>security.insecureAPI.UncheckedReturn</b></td><td>Warn on uses of functions whose return values must be always checked.</td> -</tr> -<tr> -<td><b>security.insecureAPI.getpw</b></td><td>Warn on uses of the 'getpw' function.</td> -</tr> -<tr> -<td><b>security.insecureAPI.gets</b></td><td>Warn on uses of the 'gets' function.</td> -</tr> -<tr> -<td><b>security.insecureAPI.mkstemp</b></td><td>Warn when 'mkstemp' is passed fewer than 6 X's in the format string.</td> -</tr> -<tr> -<td><b>security.insecureAPI.mktemp</b></td><td>Warn on uses of the 'mktemp' function.</td> -</tr> -<tr> -<td><b>security.insecureAPI.rand</b></td><td>Warn on uses of the 'rand', 'random', and related functions.</td> -</tr> -<tr> -<td><b>security.insecureAPI.strcpy</b></td><td>Warn on uses of the 'strcpy' and 'strcat' functions.</td> -</tr> -<tr> -<td><b>security.insecureAPI.vfork</b></td><td>Warn on uses of the 'vfork' function.</td> -</tr> -<tr> -<td><b>unix.API</b></td><td>Check calls to various UNIX/Posix functions.</td> -</tr> -<tr> -<td><b>unix.Malloc</b></td><td>Check for memory leaks, double free, and use-after-free problems involving <code>malloc</code>.</td> -</tr> -<tr> -<td><b>unix.MallocSizeof</b></td><td>Check for dubious malloc arguments involving sizeof.</td> -</tr> -<tr> -<td><b>unix.MismatchedDeallocator</b></td><td>Check for mismatched deallocators (e.g. passing a pointer allocating with <code>new</code> to <code>free()</code>).</td> -</tr> -<tr> -<td><b>unix.cstring.BadSizeArg</b></td><td>Check the size argument passed into C string functions for common erroneous patterns.</td> -</tr> -<tr> -<td><b>unix.cstring.NullArg</b></td><td>Check for null pointers being passed as arguments to C string functions.</td> -</table> - -<p>In addition to these the analyzer contains numerous experimental (alpha) checkers.</p> +<h1>Available Checkers</h1> +The analyzer performs checks that are categorized into families or "checkers". The +default set of checkers covers a variety of checks targeted at finding security +and API usage bugs, dead code, and other logic errors. See the +<a href = "#default_checkers">Default Checkers</a> list below. In addition to +these, the analyzer contains a number of <a href = "alpha_checks.html"> +Experimental (Alpha) Checkers</a>. <h3>Writeups with examples of some of the bugs that the analyzer finds</h3> - <ul> <li><a href="http://www.mobileorchard.com/bug-finding-with-clang-5-resources-to-get-you-started/">Bug Finding With Clang: 5 Resources To Get You Started</a></li> <li><a href="http://fruitstandsoftware.com/blog/index.php/2008/08/finding-memory-leaks-with-the-llvmclang-static-analyzer/#comment-2">Finding Memory Leaks With The LLVM/Clang Static Analyzer</a></li> @@ -190,9 +33,1226 @@ <li><a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-03-06-using-the-clang-static-analyzer.html">Mike Ash - Using the Clang Static Analyzer</a></li> </ul> +<h2 id="default_checkers">Default Checkers</h2> +<ul> +<li><a href="#core_checkers">Core Checkers</a> model core language features and perform general-purpose checks such as division by zero, null pointer dereference, usage of uninitialized values, etc.</li> +<li><a href="#cplusplus_checkers">C++ Checkers</a> perform C++-specific checks</li> +<li><a href="#deadcode_checkers">Dead Code Checkers</a> check for unused code</li> +<li><a href="#osx_checkers">OS X Checkers</a> perform Objective-C-specific checks and check the use of Apple's SDKs (OS X and iOS)</li> +<li><a href="#security_checkers">Security Checkers</a> check for insecure API usage and perform checks based on the CERT Secure Coding Standards</li> +<li><a href="#unix_checkers">Unix Checkers</a> check the use of Unix and POSIX APIs</li> +</ul> + +<!------------------------------------ core -----------------------------------> +<h3 id="core_checkers">Core Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.CallAndMessage</span><span class="lang"> +(C, C++, ObjC)</span><div class="descr"> +Check for logical errors for function calls and Objective-C message expressions +(e.g., uninitialized arguments, null function pointers).</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +// C +struct S { + int x; +}; + +void f(struct S s); + +void test() { + struct S s; + f(s); // warn: passed-by-value arg contain uninitialized data +} +</pre></div> +<div class="example"><pre> +// C +void test() { + void (*foo)(void); + foo(); // warn: function pointer is uninitialized +} +</pre></div> +<div class="example"><pre> +// C +void test() { + void (*foo)(void); + foo = 0; + foo(); // warn: function pointer is null +} +</pre></div> +<div class="example"><pre> +// C++ +class C { +public: + void f(); +}; + +void test() { + C *pc; + pc->f(); // warn: object pointer is uninitialized +} +</pre></div> +<div class="example"><pre> +// C++ +class C { +public: + void f(); +}; + +void test() { + C *pc = 0; + pc->f(); // warn: object pointer is null +} +</pre></div> +<div class="example"><pre> +// Objective-C +@interface MyClass : NSObject +@property (readwrite,assign) id x; +- (long double)longDoubleM; +@end + +void test() { + MyClass *obj1; + long double ld1 = [obj1 longDoubleM]; + // warn: receiver is uninitialized +} +</pre></div> +<div class="example"><pre> +// Objective-C +@interface MyClass : NSObject +@property (readwrite,assign) id x; +- (long double)longDoubleM; +@end + +void test() { + MyClass *obj1; + id i = obj1.x; // warn: uninitialized object pointer +} +</pre></div> +<div class="example"><pre> +// Objective-C +@interface Subscriptable : NSObject +- (id)objectAtIndexedSubscript:(unsigned int)index; +@end + +@interface MyClass : Subscriptable +@property (readwrite,assign) id x; +- (long double)longDoubleM; +@end + +void test() { + MyClass *obj1; + id i = obj1[0]; // warn: uninitialized object pointer +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.DivideZero</span><span class="lang"> +(C, C++, ObjC)</span><div class="descr"> +Check for division by zero.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(int z) { + if (z == 0) + int x = 1 / z; // warn +} +</pre></div> +<div class="example"><pre> +void test() { + int x = 1; + int y = x % 0; // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.NonNullParamChecker</span><span class="lang"> +(C, C++, ObjC)</span><div class="descr"> +Check for null pointers passed as arguments to a function whose arguments are +marked with the <code>nonnull</code> attribute.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int f(int *p) __attribute__((nonnull)); + +void test(int *p) { + if (!p) + f(p); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.NullDereference</span><span class="lang"> +(C, C++, ObjC)</span><div class="descr"> +Check for dereferences of null pointers.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +// C +void test(int *p) { + if (p) + return; + + int x = p[0]; // warn +} +</pre></div> +<div class="example"><pre> +// C +void test(int *p) { + if (!p) + *p = 0; // warn +} +</pre></div> +<div class="example"><pre> +// C++ +class C { +public: + int x; +}; + +void test() { + C *pc = 0; + int k = pc->x; // warn +} +</pre></div> +<div class="example"><pre> +// Objective-C +@interface MyClass { +@public + int x; +} +@end + +void test() { + MyClass *obj = 0; + obj->x = 1; // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.StackAddressEscape</span><span class="lang"> +(C)</span><div class="descr"> +Check that addresses of stack memory do not escape the function.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +char const *p; + +void test() { + char const str[] = "string"; + p = str; // warn +} +</pre></div> +<div class="example"><pre> +void* test() { + return __builtin_alloca(12); // warn +} +</pre></div> +<div class="example"><pre> +void test() { + static int *x; + int y; + x = &y; // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.UndefinedBinaryOperatorResult</span><span class="lang"> +(C)</span><div class="descr"> +Check for undefined results of binary operators.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + int y = x + 1; // warn: left operand is garbage +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.VLASize</span><span class="lang"> +(C)</span><div class="descr"> +Check for declarations of VLA of undefined or zero size.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + int vla1[x]; // warn: garbage as size +} +</pre></div> +<div class="example"><pre> +void test() { + int x = 0; + int vla2[x]; // warn: zero size +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.uninitialized.ArraySubscript</span><span class="lang"> +(C)</span><div class="descr"> +Check for uninitialized values used as array subscripts.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int i, a[10]; + int x = a[i]; // warn: array subscript is undefined +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.uninitialized.Assign</span><span class="lang"> +(C)</span><div class="descr"> +Check for assigning uninitialized values.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + x |= 1; // warn: left expression is unitialized +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.uninitialized.Branch</span><span class="lang"> +(C)</span><div class="descr"> +Check for uninitialized values used as branch conditions.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + if (x) // warn + return; +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.uninitialized.CapturedBlockVariable</span><span class="lang"> +(C)</span><div class="descr"> +Check for blocks that capture uninitialized values.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + ^{ int y = x; }(); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +core.uninitialized.UndefReturn</span><span class="lang"> +(C)</span><div class="descr"> +Check for uninitialized values being returned to the caller.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int test() { + int x; + return x; // warn +} +</pre></div></div></td></tr> + +</tbody></table> + +<!------------------------------------ C++ ------------------------------------> +<h3 id="cplusplus_checkers">C++ Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +cplusplus.NewDelete</span><span class="lang"> +(C++)</span><div class="descr"> +Check for double-free, use-after-free and offset problems involving C++ <code> +delete</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void f(int *p); + +void testUseMiddleArgAfterDelete(int *p) { + delete p; + f(p); // warn: use after free +} +</pre></div> +<div class="example"><pre> +class SomeClass { +public: + void f(); +}; + +void test() { + SomeClass *c = new SomeClass; + delete c; + c->f(); // warn: use after free +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = (int *)__builtin_alloca(sizeof(int)); + delete p; // warn: deleting memory allocated by alloca +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = new int; + delete p; + delete p; // warn: attempt to free released +} +</pre></div> +<div class="example"><pre> +void test() { + int i; + delete &i; // warn: delete address of local +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = new int[1]; + delete[] (++p); + // warn: argument to 'delete[]' is offset by 4 bytes + // from the start of memory allocated by 'new[]' +} +</pre></div></div></td></tr> + +</tbody></table> + +<!--------------------------------- dead code ---------------------------------> +<h3 id="deadcode_checkers">Dead Code Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +deadcode.DeadStores</span><span class="lang"> +(C)</span><div class="descr"> +Check for values stored to variables that are never read afterwards.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x; + x = 1; // warn +} +</pre></div></div></td></tr> + +</tbody></table> + +<!---------------------------------- OS X ------------------------------------> +<h3 id="osx_checkers">OS X Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +osx.API</span><span class="lang"> +(C)</span><div class="descr"> +Check for proper uses of various Apple APIs:<div class=functions> +dispatch_once</div></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + dispatch_once_t pred = 0; + dispatch_once(&pred, ^(){}); // warn: dispatch_once uses local +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.SecKeychainAPI</span><span class="lang"> +(C)</span><div class="descr"> +Check for improper uses of the Security framework's Keychain APIs:<div class=functions> +SecKeychainItemCopyContent<br> +SecKeychainFindGenericPassword<br> +SecKeychainFindInternetPassword<br> +SecKeychainItemFreeContent<br> +SecKeychainItemCopyAttributesAndData<br> +SecKeychainItemFreeAttributesAndData</div></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + unsigned int *ptr = 0; + UInt32 length; + + SecKeychainItemFreeContent(ptr, &length); + // warn: trying to free data which has not been allocated +} +</pre></div> +<div class="example"><pre> +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, outData); + // warn: data is not released +} +</pre></div> +<div class="example"><pre> +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + + SecKeychainItemFreeContent(ptr, outData); + // warn: only call free if a non-NULL buffer was returned +} +</pre></div> +<div class="example"><pre> +void test() { + unsigned int *ptr = 0; + UInt32 *length = 0; + void *outData; + + OSStatus st = + SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + + st = SecKeychainItemCopyContent(2, ptr, ptr, length, &outData); + // warn: release data before another call to the allocator + + if (st == noErr) + SecKeychainItemFreeContent(ptr, outData); +} +</pre></div> +<div class="example"><pre> +void test() { + SecKeychainItemRef itemRef = 0; + SecKeychainAttributeInfo *info = 0; + SecItemClass *itemClass = 0; + SecKeychainAttributeList *attrList = 0; + UInt32 *length = 0; + void *outData = 0; + + OSStatus st = + SecKeychainItemCopyAttributesAndData(itemRef, info, + itemClass, &attrList, + length, &outData); + + SecKeychainItemFreeContent(attrList, outData); + // warn: deallocator doesn't match the allocator +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.AtSync</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for nil pointers used as mutexes for <code>@synchronized</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(id x) { + if (!x) + @synchronized(x) {} // warn: nil value used as mutex +} +</pre></div> +<div class="example"><pre> +void test() { + id y; + @synchronized(y) {} // warn: uninitialized value used as mutex +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.ClassRelease</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for sending <code>retain</code>, <code>release</code>, or <code> +autorelease</code> directly to a class.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +@interface MyClass : NSObject +@end + +void test(void) { + [MyClass release]; // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.IncompatibleMethodTypes</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for an incompatible type signature when overriding an Objective-C method.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +@interface MyClass1 : NSObject +- (int)foo; +@end -</div> -</div> +@implementation MyClass1 +- (int)foo { return 1; } +@end + +@interface MyClass2 : MyClass1 +- (float)foo; +@end + +@implementation MyClass2 +- (float)foo { return 1.0; } // warn +@end +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +alpha.osx.cocoa.MissingSuperCall</span><span class="lang"> +(ObjC)</span><div class="descr"> +Warn about Objective-C methods that lack a necessary call to super. (Note: The +compiler now has a warning for methods annotated with <code>objc_requires_super</code> +attribute. The checker exists to check methods in the Cocoa frameworks +that haven't yet adopted this attribute.)</div></div></td> +<td><div class="example"><pre> +@interface Test : UIViewController +@end +@implementation test +- (void)viewDidLoad {} // warn +@end +</pre></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.NSAutoreleasePool</span><span class="lang"> +(ObjC)</span><div class="descr"> +Warn for suboptimal uses of NSAutoreleasePool in Objective-C +GC mode (<code>-fobjc-gc</code> compiler option).</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [pool release]; // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.NSError</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check usage of <code>NSError**</code> parameters.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +@interface A : NSObject +- (void)foo:(NSError **)error; +@end + +@implementation A +- (void)foo:(NSError **)error { + // warn: method accepting NSError** should have a non-void + // return value +} +@end +</pre></div> +<div class="example"><pre> +@interface A : NSObject +- (BOOL)foo:(NSError **)error; +@end + +@implementation A +- (BOOL)foo:(NSError **)error { + *error = 0; // warn: potential null dereference + return 0; +} +@end +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.NilArg</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for prohibited nil arguments in specific Objective-C method calls:<div class=functions> +- caseInsensitiveCompare:<br> +- compare:<br> +- compare:options:<br> +- compare:options:range:<br> +- compare:options:range:locale:<br> +- componentsSeparatedByCharactersInSet:<br> +- initWithFormat:</div></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +NSComparisonResult test(NSString *s) { + NSString *aString = nil; + return [s caseInsensitiveCompare:aString]; + // warn: argument to 'NSString' method + // 'caseInsensitiveCompare:' cannot be nil +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.RetainCount</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for leaks and violations of the Cocoa Memory Management rules.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + NSString *s = [[NSString alloc] init]; // warn +} +</pre></div> +<div class="example"><pre> +CFStringRef test(char *bytes) { + return CFStringCreateWithCStringNoCopy( + 0, bytes, NSNEXTSTEPStringEncoding, 0); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.SelfInit</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check that <code>self</code> is properly initialized inside an initializer +method.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +@interface MyObj : NSObject { + id x; +} +- (id)init; +@end + +@implementation MyObj +- (id)init { + [super init]; + x = 0; // warn: instance variable used while 'self' is not + // initialized + return 0; +} +@end +</pre></div> +<div class="example"><pre> +@interface MyObj : NSObject +- (id)init; +@end + +@implementation MyObj +- (id)init { + [super init]; + return self; // warn: returning uninitialized 'self' +} +@end +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.UnusedIvars</span><span class="lang"> +(ObjC)</span><div class="descr"> +Warn about private ivars that are never used.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +@interface MyObj : NSObject { +@private + id x; // warn +} +@end + +@implementation MyObj +@end +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.cocoa.VariadicMethodTypes</span><span class="lang"> +(ObjC)</span><div class="descr"> +Check for passing non-Objective-C types to variadic collection initialization +methods that expect only Objective-C types.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + [NSSet setWithObjects:@"Foo", "Bar", nil]; + // warn: argument should be an ObjC pointer type, not 'char *' +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.coreFoundation.CFError</span><span class="lang"> +(C)</span><div class="descr"> +Check usage of <code>CFErrorRef*</code> parameters.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(CFErrorRef *error) { + // warn: function accepting CFErrorRef* should have a + // non-void return +} +</pre></div> +<div class="example"><pre> +int foo(CFErrorRef *error) { + *error = 0; // warn: potential null dereference + return 0; +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.coreFoundation.CFNumber</span><span class="lang"> +(C)</span><div class="descr"> +Check for improper uses of <code>CFNumberCreate</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +CFNumberRef test(unsigned char x) { + return CFNumberCreate(0, kCFNumberSInt16Type, &x); + // warn: 8 bit integer is used to initialize a 16 bit integer +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.coreFoundation.CFRetainRelease</span><span class="lang"> +(C)</span><div class="descr"> +Check for null arguments to <code>CFRetain</code>, <code>CFRelease</code>, +<code>CFMakeCollectable</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(CFTypeRef p) { + if (!p) + CFRetain(p); // warn +} +</pre></div> +<div class="example"><pre> +void test(int x, CFTypeRef p) { + if (p) + return; + + CFRelease(p); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.coreFoundation.containers.OutOfBounds</span><span class="lang"> +(C)</span><div class="descr"> +Checks for index out-of-bounds when using <code>CFArray</code> API.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + CFArrayRef A = CFArrayCreate(0, 0, 0, &kCFTypeArrayCallBacks); + CFArrayGetValueAtIndex(A, 0); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +osx.coreFoundation.containers.PointerSizedValues</span><span class="lang"> +(C)</span><div class="descr"> +Warns if <code>CFArray</code>, <code>CFDictionary</code>, <code>CFSet</code> are +created with non-pointer-size values.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x[] = { 1 }; + CFArrayRef A = CFArrayCreate(0, (const void **)x, 1, + &kCFTypeArrayCallBacks); // warn +} +</pre></div></div></td></tr> + +</tbody></table> + +<!------------------------------- security ------------------------------------> +<h3 id="security_checkers">Security Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +security.FloatLoopCounter</span><span class="lang"> +(C)</span><div class="descr"> +Warn on using a floating point value as a loop counter (CERT: FLP30-C, +FLP30-CPP).</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + for (float x = 0.1f; x <= 1.0f; x += 0.1f) {} // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.UncheckedReturn</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of functions whose return values must be always checked:<div class=functions> +setuid<br> +setgid<br> +seteuid<br> +setegid<br> +setreuid<br> +setregid</div></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + setuid(1); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.getpw</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of the <code>getpw</code> function.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + char buff[1024]; + getpw(2, buff); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.gets</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of the <code>gets</code> function.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + char buff[1024]; + gets(buff); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.mkstemp</span><span class="lang"> +(C)</span><div class="descr"> +Warn when <code>mktemp</code>, <code>mkstemp</code>, <code>mkstemps</code> or +<code>mkdtemp</code> is passed fewer than 6 +X's in the format string.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + mkstemp("XX"); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.mktemp</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of the <code>mktemp</code> function.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + char *x = mktemp("/tmp/zxcv"); // warn: insecure, use mkstemp +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.rand</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of inferior random number generating functions (only if <code>arc4random</code> +function is available):<div class=functions> +drand48<br> +erand48<br> +jrand48<br> +lcong48<br> +lrand48<br> +mrand48<br> +nrand48<br> +random<br> +rand_r</div></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + random(); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.strcpy</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of the <code>strcpy</code> and <code>strcat</code> functions.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + char x[4]; + char *y = "abcd"; + + strcpy(x, y); // warn +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +security.insecureAPI.vfork</span><span class="lang"> +(C)</span><div class="descr"> +Warn on uses of the <code>vfork</code> function.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + vfork(); // warn +} +</pre></div></div></td></tr> + +</tbody></table> + +<!--------------------------------- unix --------------------------------------> +<h3 id="unix_checkers">Unix Checkers</h3> +<table class="checkers"> +<colgroup><col class="namedescr"><col class="example"></colgroup> + +<thead> +<tr><td><div class="namedescr">Name, Description</div></td> +<td><div class="example">Example</div></td></tr> +</thead> + +<tbody> +<tr><td><div class="namedescr expandable"><span class="name"> +unix.API</span><span class="lang"> +(C)</span><div class="descr"> +Check calls to various UNIX/POSIX functions:<div class=functions> +open<br> +pthread_once<br> +calloc<br> +malloc<br> +realloc<br> +alloca<br> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +// Currently the check is performed for apple targets only. +void test(const char *path) { + int fd = open(path, O_CREAT); + // warn: call to 'open' requires a third argument when the + // 'O_CREAT' flag is set +} +</pre></div> +<div class="example"><pre> +void f(); + +void test() { + pthread_once_t pred = {0x30B1BCBA, {0}}; + pthread_once(&pred, f); + // warn: call to 'pthread_once' uses the local variable +} +</pre></div> +<div class="example"><pre> +void test() { + void *p = malloc(0); // warn: allocation size of 0 bytes +} +</pre></div> +<div class="example"><pre> +void test() { + void *p = calloc(0, 42); // warn: allocation size of 0 bytes +} +</pre></div> +<div class="example"><pre> +void test() { + void *p = malloc(1); + p = realloc(p, 0); // warn: allocation size of 0 bytes +} +</pre></div> +<div class="example"><pre> +void test() { + void *p = alloca(0); // warn: allocation size of 0 bytes +} +</pre></div> +<div class="example"><pre> +void test() { + void *p = valloc(0); // warn: allocation size of 0 bytes +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +unix.Malloc</span><span class="lang"> +(C)</span><div class="descr"> +Check for memory leaks, double free, and use-after-free and offset problems +involving <code>malloc</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int *p = malloc(1); + free(p); + free(p); // warn: attempt to free released memory +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = malloc(sizeof(int)); + free(p); + *p = 1; // warn: use after free +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = malloc(1); + if (p) + return; // warn: memory is never released +} +</pre></div> +<div class="example"><pre> +void test() { + int a[] = { 1 }; + free(a); // warn: argument is not allocated by malloc +} +</pre></div> +<div class="example"><pre> +void test() { + int *p = malloc(sizeof(char)); + p = p - 1; + free(p); // warn: argument to free() is offset by -4 bytes +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +unix.MallocSizeof</span><span class="lang"> +(C)</span><div class="descr"> +Check for dubious <code>malloc</code>, <code>calloc</code> or +<code>realloc</code> arguments involving <code>sizeof</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + long *p = malloc(sizeof(short)); + // warn: result is converted to 'long *', which is + // incompatible with operand type 'short' + free(p); +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +unix.MismatchedDeallocator</span><span class="lang"> +(C, C++, ObjC)</span><div class="descr"> +Check for mismatched deallocators (e.g. passing a pointer allocating +with <code>new</code> to <code>free()</code>).</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +// C, C++ +void test() { + int *p = (int *)malloc(sizeof(int)); + delete p; // warn +} +</pre></div> +<div class="example"><pre> +// C, C++ +void __attribute((ownership_returns(malloc))) *user_malloc(size_t); + +void test() { + int *p = (int *)user_malloc(sizeof(int)); + delete p; // warn +} +</pre></div> +<div class="example"><pre> +// C, C++ +void test() { + int *p = new int; + free(p); // warn +} +</pre></div> +<div class="example"><pre> +// C, C++ +void test() { + int *p = new int[1]; + realloc(p, sizeof(long)); // warn +} +</pre></div> +<div class="example"><pre> +// C, C++ +template <typename T> +struct SimpleSmartPointer { + T *ptr; + + explicit SimpleSmartPointer(T *p = 0) : ptr(p) {} + ~SimpleSmartPointer() { + delete ptr; // warn + } +}; + +void test() { + SimpleSmartPointer<int> a((int *)malloc(4)); +} +</pre></div> +<div class="example"><pre> +// C++ +void test() { + int *p = (int *)operator new(0); + delete[] p; // warn +} +</pre></div> +<div class="example"><pre> +// Objective-C, C++ +void test(NSUInteger dataLength) { + int *p = new int; + NSData *d = [NSData dataWithBytesNoCopy:p + length:sizeof(int) freeWhenDone:1]; + // warn +dataWithBytesNoCopy:length:freeWhenDone: cannot take + // ownership of memory allocated by 'new' +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +unix.cstring.BadSizeArg</span><span class="lang"> +(C)</span><div class="descr"> +Check the size argument passed to <code>strncat</code> for common erroneous +patterns. Use <code>-Wno-strncat-size</code> compiler option to mute other +<code>strncat</code>-related compiler warnings. +</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + char dest[3]; + strncat(dest, "***", sizeof(dest)); + // warn: potential buffer overflow +} +</pre></div></div></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +unix.cstring.NullArg</span><span class="lang"> +(C)</span><div class="descr"> +Check for null pointers being passed as arguments to C string functions:<div class=functions> +strlen<br> +strnlen<br> +strcpy<br> +strncpy<br> +strcat<br> +strncat<br> +strcmp<br> +strncmp<br> +strcasecmp<br> +strncasecmp</div></div></div></td> +<td><div class="example"><pre> +int test() { + return strlen(0); // warn +} +</pre></div></td></tr> + +</tbody></table> + +</div> <!-- page --> +</div> <!-- content --> </body> </html> - diff --git a/www/analyzer/content.css b/www/analyzer/content.css index 929d5200a3..a10730899e 100644 --- a/www/analyzer/content.css +++ b/www/analyzer/content.css @@ -38,7 +38,7 @@ IMG.img_slide { #content { clear: left; - padding: 1em 2em 0 2em; + padding: 1em 2em 1em 2em; background-color: #ffffff; } @@ -54,9 +54,7 @@ table.options thead { text-align:left; border-top: 2px solid #cccccc; border-bottom: 2px solid #cccccc; - font-weight: bold; font-family: Verdana; - table-layout: fixed; - width: 100% + font-weight: bold; font-family: Verdana } table.options { border: 1px #cccccc solid } table.options { border-collapse: collapse; border-spacing: 0px } @@ -64,7 +62,6 @@ table.options { margin-left:0px; margin-top:20px; margin-bottom:20px } table.options td { border-bottom: 1px #cccccc dotted } table.options td { padding:5px; padding-left:8px; padding-right:8px } table.options td { text-align:left; font-size:9pt } -table.options col.option { width:207px } table.checkers { border: 1px #cccccc solid; @@ -76,28 +73,29 @@ table.checkers { word-wrap :break-word; font-size: 100%; } - table.checkers thead { background-color:#eee; color:#666666; border-top: 2px solid #cccccc; border-bottom: 2px solid #cccccc; font-weight: bold; font-family: Verdana; } - -table.checkers td { - padding:5px; padding-left:8px; padding-right:8px; - border-right: 1px #cccccc dotted; - border-bottom: 1px #cccccc dotted; -} - +table.checkers td { border-right: 1px #cccccc dotted; border-bottom: 1px #cccccc dotted; } table.checkers td.aligned { text-align: center; vertical-align: middle; } table.checkers col.namedescr { width: 45% } table.checkers col.example { width: 55% } table.checkers col.progress { width: 84px } -table.checkers pre { margin:1px; font-size: 100%; word-wrap :break-word; } -table.checkers .name { font-weight:bold; } -table.checkers .checked { background-color:#81F781; } -table.checkers .commented { color:#909090; } +table.checkers thead div.example, +table.checkers div.namedescr, +table.checkers div.exampleContainer { overflow: hidden; padding: 5px 8px 10px 8px } +/* table.checkers tbody div.example { font-family: monospace; white-space: pre } */ +table.checkers div.example { border-top:1px #cccccc dashed; width:100%; padding-top: 5px; margin-top: 5px } +table.checkers tbody div.example:first-child { border-top:none; padding-top: 0px; margin-top: 0px } +table.checkers span.name { font-weight: bold } +table.checkers span.lang { font-weight: bold; padding-left: 7px; /* display:block; */ } +table.checkers div.descr { margin-top:7px } +table.checkers div.functions { margin-top: 2px; font-style: italic; font-size: 90%; color:#00B } +table.checkers pre { margin: 1px; font-size: 100%; word-wrap: break-word } +table.checkers p { margin: 10px 0px 0px 0px; } /* Collapsing Trees: http://dbtree.megalingo.com/web/demo/simple-collapsible-tree.cfm */ #collapsetree, #collapsetree a:link, #collapsetree li a:link, #collapsetree a:visited, #collapsetree li a:visited{color:#000;text-decoration:none} diff --git a/www/analyzer/potential_checkers.html b/www/analyzer/potential_checkers.html index 335e50d848..d3b1209ec3 100644 --- a/www/analyzer/potential_checkers.html +++ b/www/analyzer/potential_checkers.html @@ -7,8 +7,9 @@ <link type="text/css" rel="stylesheet" href="menu.css"> <script type="text/javascript" src="scripts/menu.js"></script> <script type="text/javascript" src="scripts/dbtree.js"></script> + <script type="text/javascript" src="scripts/expandcollapse.js"></script> </head> -<body> +<body onload="initExpandCollapse()"> <div id="page"> @@ -21,120 +22,88 @@ <p>This page contains a list of potential checkers to implement in the static analyzer. If you are interested in contributing to the analyzer's development, this is a good resource to help you get started. The specific names of the checkers are subject to review, and are provided here as suggestions.</p> <!-- ========================= allocation/deallocation ======================= --> -<h3>allocation/deallocation</h3> +<h3>memory</h3> <table class="checkers"> <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">memory.LeakNeverReleased<br> -(C, C++)</span><br><br> -Memory may be never released, potential leak of memory -</td><td> -<pre> -#include <stdlib.h> - -int f() {}; - -void test() { - int *p1 = (int*)malloc(sizeof(int)); // warn - int *p2 = new int; // warn - int x = f(); - if (x==1) - return; - delete p2; -} -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15237">PR15237</a> -</td></tr> - -<tr><td><span class="name">memory.MismatchedFree -<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> -Mismatched deallocation function is used -</td><td><pre> -#include <stdlib.h> +<tr><td><div class="namedescr expandable"><span class="name"> +memory.LeakEvalOrder</span><span class="lang"> +(C, C++)</span><div class="descr"> +Potential memory leaks caused by an undefined argument evaluation order. +<p>Source: <a href="http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_ptr.htm#BestPractices"> +boost docs: shared_ptr</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void f(int, int); +int g(void *); +int h() __attribute__((noreturn)); void test() { - int *p1 = new int; - int *p2 = new int[1]; - - free(p1); // warn - free(p2); // warn + // It is possible that 'malloc(1)' is called first, + // then 'h()', that is (or calls) noreturn and eventually + // 'g()' is never called. + f(g(malloc(1)), h()); // warn: 'g()' may never be called. } -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15238">PR15238</a> -</td></tr> - -<tr><td><span class="name">memory.LeakPtrValChanged -<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> -Potential memory leak: a pointer to newly allocated data loses its original -value -</td><td><pre> -#include <stdlib.h> - -void f(const int *); -void g(int *); - -void test() { - int *p1 = new int; - p1++; // warn - int *p2 = (int *)malloc(sizeof(int)); - p2 = p1; // warn - int *p3 = new int; - f(p3); - p3++; // warn - int *p4 = new int; - f(p4); - p4++; // ok -} -</pre></td><td class="aligned">done at r174678 (C case) -</td></tr> - -<tr><td><span class="name">memory.LeakEvalOrder<br> -(C, C++)</span><br><br> -Potential memory leak: argument evaluation order is undefined, g() may never be called -</td><td><pre> -#include <stdlib.h> - -void f1(int, int); -void f2(int*, int*); -int g(int *) { throw 1; }; -int h(); +</pre></div> +<div class="example"><pre> +void f(int, int); +int g(int *); +int h() { throw 1; }; void test() { - f1(g(new int), h()); // warn - f1(g((int *)malloc(sizeof(int))), h()); // warn - f2(new int, new int); -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">memory.DstBufferTooSmall -<br>(C, C++)</span><br><br> -Destination buffer too small -</td><td><pre> -#include <string.h> - + // It is possible that 'new int' is called first, + // then 'h()', that throws an exception and eventually + // 'g()' is never called. + f(g(new int), h()); // warn: 'g()' may never be called. +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +memory.DstBufferTooSmall</span><span class="lang"> +(C, C++)</span><div class="descr"> +Destination buffer passed to memory function is too small. +<br>Note: <span class="name">security.insecureAPI.strcpy</span> currently warns +on usage of <code>strcpy</code> and suggests to replace it. +<br>Note: <span class="name">alpha.unix.CStringChecker</span> contains some similar checks. +<p>Source: <a href="https://cwe.mitre.org/data/definitions/120.html">CWE-120</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test() { const char* s1 = "abc"; char *s2 = new char; strcpy(s2, s1); // warn - +} +</pre></div> +<div class="example"><pre> +void test() { int* p1 = new int[3]; int* p2 = new int; memcpy(p2, p1, 3); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">memory.NegativeArraySize -<br>enhancement to experimental.security.MallocOverflow<br>(C, C++) -</span><br><br> -'n' is used to specify the buffer size may be negative -</td><td><pre> -#include <stdlib.h> +<tr><td><div class="namedescr expandable"><span class="name"> +memory.NegativeArraySize</span><span class="lang"> +(C, C++)</span><div class="descr"> +'n' is used to specify the buffer size may be negative. +<br>Note: possibly an enhancement to <span class="name"> +alpha.security.MallocOverflow</span>. +<p>Source: <a href="http://cwe.mitre.org/data/definitions/20.html">CWE-20, +Example 2</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test() { int *p; int n1 = -1; p = new int[n1]; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> </table> @@ -144,42 +113,45 @@ void test() { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">ctordtor.ExptInsideDtorExplicit<br> -(C++)</span><br><br> -It is dangerous to let an exception leave a destructor. Using try..catch will -solve the problem. -</td><td><pre> -void f(); - +<tr><td><div class="namedescr expandable"><span class="name"> +ctordtor.ExptInsideDtor</span><span class="lang"> +(C++)</span><div class="descr"> +It is dangerous to let an exception leave a destructor. +Using <code>try..catch</code> solves the problem. +<p>Source: Scott Meyers "More Effective C++", item 11: Prevent exceptions from +leaving destructors.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { A() {} ~A() { throw 1; } // warn }; -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">ctordtor.ExptInsideDtorImplicit<br> -(C++)</span><br><br> -Calls to functions inside a destructor that are known to throw exceptions is -dangerous. Using try..catch will solve the problem. -</td><td><pre> -void f() { throw 1; }; +</pre></div> +<div class="example"><pre> +void f() throw(int); class A { A() {} ~A() { f(); } // warn }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">ctordtor.PlacementSelfCopy<br> -(C++11)</span><br><br> -For a placement copy or move, it is almost certainly an error if the constructed object is also the object being copied from. -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +ctordtor.PlacementSelfCopy</span><span class="lang"> +(C++11)</span><div class="descr"> +For a placement copy or move, it is almost certainly an error if the +constructed object is also the object being copied from.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A {}; void test(A *dst, A *src) { ::new (dst) A(*dst); // warn (should be 'src') } -</pre></td><td class="aligned"><!--rdar://problem/13688366--></td></tr> +</pre></div></div></td> +<td class="aligned"><!--rdar://problem/13688366--></td></tr> </table> @@ -189,37 +161,55 @@ void test(A *dst, A *src) { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">valist.Uninitialized</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +valist.Uninitialized</span><span class="lang"> +(C)</span><div class="descr"> Calls to the <code>va_arg</code>, <code>va_copy</code>, or <code>va_end</code> macro must happen after calling <code>va_start</code> and -before calling <code>va_end</code>. -</td><td><pre> +before calling <code>va_end</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <stdarg.h> void test(int x, ...) { va_list args; int y = va_arg(args, int); // warn +} +</pre></div> +<div class="example"><pre> +#include <stdarg.h> + +void test(int x, ...) { + va_list args; va_start(args, x); - va_end(args, x); + va_end(args); int z = va_arg(args, int); // warn } -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812">PR16811</a></td></tr> +</pre></div></div></td> +<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812"> +PR16811</a></td></tr> -<tr><td><span class="name">valist.Unterminated</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +valist.Unterminated</span><span class="lang"> +(C)</span><div class="descr"> Every <code>va_start</code> must be matched by a <code>va_end</code>. A va_list can only be ended once. -<i>This should be folded into the generalized "ownership checker" described on the <a href="open_projects.html">Open Projects</a> page.</i> -</td><td><pre> +<i>This should be folded into the generalized "ownership checker" +described on the <a href="open_projects.html"> +Open Projects</a> page.</i></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <stdarg.h> void test(int x, ...) { va_list args; va_start(args, x); int y = x + va_arg(args, int); - // missing va_end -} -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812">PR16812</a></td></tr> +} // warn: missing va_end +</pre></div></div></td> +<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812"> +PR16812</a></td></tr> </table> @@ -229,34 +219,48 @@ void test(int x, ...) { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">exceptions.ThrowSpecButNotThrow -<br>(C++)</span><br><br> -Function prototype has throw(T) specifier but the function do not throw -</td><td><pre> -void f() throw(int) { // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">exceptions.NoThrowSpecButThrows -<br>(C++)</span><br><br> -An exception is throw from a function having the throw() specifier -</td><td><pre> -void f() throw() { +<tr><td><div class="namedescr expandable"><span class="name"> +exceptions.ThrowSpecButNotThrow</span><span class="lang"> +(C++)</span><div class="descr"> +Function declaration has a <code>throw(<i>type</i>)</code> specifier but the +function do not throw exceptions.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() throw(int) { +} // warn +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +exceptions.NoThrowSpecButThrows</span><span class="lang"> +(C++)</span><div class="descr"> +An exception is throw from a function having a <code>throw()</code> +specifier.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() throw() { throw(1); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">exceptions.ThrownTypeDiffersSpec -<br>(C++)</span><br><br> -The type of a thrown exception differs from those specified in the throw(T) -specifier -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +exceptions.ThrownTypeDiffersSpec</span><span class="lang"> +(C++)</span><div class="descr"> +The type of a thrown exception differs from those specified in +a <code>throw(<i>type</i>)</code> specifier.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> struct S{}; -void f() throw(int) { + +void test() throw(int) { S s; throw (s); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> </table> @@ -266,25 +270,36 @@ void f() throw(int) { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">smartptr.SmartPtrInit<br> -(C++)</span><br><br> -C++03: auto_ptr should store a pointer to an object obtained via new as allocated -memory will be cleaned using delete<br> -C++11: one should use unique_ptr<T[]> to keep a pointer to memory -allocated by new[]<br> -C++11: to keep a pointer to memory allocated by new[] in a shared_ptr one -should use a custom deleter that calls delete[] -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +smartptr.SmartPtrInit</span><span class="lang"> +(C++)</span><div class="descr"> +C++03: <code>auto_ptr</code> should store a pointer to an object obtained via +new as allocated memory will be cleaned using <code>delete</code>.<br> +C++11: one should use <code>unique_ptr<<i>type</i>[]></code> to keep a +pointer to memory allocated by <code>new[]</code>.<br> +C++11: to keep a pointer to memory allocated by <code>new[]</code> in +a <code>shared_ptr</code> one should use a custom deleter that calls <code> +delete[].</code>. +<p>Source: C++03 20.4.5p1; C++11 <code>auto_ptr</code> is deprecated (D.10).</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <stdlib.h> #include <memory> void test() { std::auto_ptr<int> p1(new int); // Ok std::auto_ptr<int> p2(new int[3]); // warn - std::auto_ptr<int> - p3((int *)malloc(sizeof(int))); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +#include <stdlib.h> +#include <memory> + +void test() { + std::auto_ptr<int> p((int *)malloc(sizeof(int))); // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> </table> @@ -294,40 +309,78 @@ void test() { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">deadcode.UnmodifiedVariable -<br>(C, C++)</span><br><br> -A variable is never modified but was not declared const and is not a reference. -<br><br> -<i>(opt-in checker)</i> -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +deadcode.UnmodifiedVariable</span><span class="lang"> +(C, C++)</span><div class="descr"> +A variable is never modified but was not declared const and is not a +reference.<br><br><i>(opt-in checker)</i></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> extern int computeDelta(); -int foo(bool cond) { +int test(bool cond) { int i = 0; if (cond) { const int delta = computeDelta(); - // Forgot to modify 'i'. + // warn: forgot to modify 'i' } return i; } -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16890">PR16890</a></td></tr> +</pre></div></div></td> +<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16890">PR16890</a></td></tr> + +<tr><td><div class="namedescr expandable"><span class="name"> +deadcode.IdempotentOperations</span><span class="lang"> +(C)</span><div class="descr"> +Warn about idempotent operations.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int x = 7; + x = x; // warn: value is always the same +} +</pre></div> +<div class="example"><pre> +void test() { + int x = 7; + x /= x; // warn: value is always 1 +} +</pre></div> +<div class="example"><pre> +void test() { + int x = 7, one = 1; + x *= one; // warn: right op is always 1 +} +</pre></div> +<div class="example"><pre> +void test() { + int x = 7, zero = 0; + x = x - zero; + // warn: the right operand to '-' is always 0 +} +</pre></div></div></td> +<td class="aligned">removed from alpha.deadcode.* at r198476</td></tr> </table> -<!-- =============================== POSIX ================================= --> +<!-- ================================ POSIX ================================ --> <h3>POSIX</h3> <table class="checkers"> <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">posix.Errno</span><br><br> -Record that <code>errno</code> is non-zero when certain functions fail. -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +posix.Errno</span><span class="lang"> +(C)</span><div class="descr"> +Record that <code>errno</code> is non-zero when certain functions +fail.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <stdlib.h> int readWrapper(int fd, int *count) { int lcount = read(fd, globalBuf, sizeof(globalBuf)); - if (lcount < 0) + if (lcount < 0) return errno; *count = lcount; return 0; @@ -338,7 +391,8 @@ void use(int fd) { if (!readWrapper(fd, &count)) print("%d", count); // should not warn } -</pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=18701">PR18701</a></td></tr> +</pre></div></div></td> +<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=18701">PR18701</a></td></tr> </table> @@ -348,11 +402,14 @@ void use(int fd) { <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">undefbehavior.ExitInDtor -<br>(C++)</span><br><br> -Undefined behavior: std::exit is called to end the program during the -destruction of an object with static storage duration -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ExitInDtor</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: <code>std::exit()</code> is called to end the program during +the destruction of an object with static storage duration. +<p>Source: C++11 3.6.1p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <cstdlib> class A { @@ -361,17 +418,20 @@ public: std::exit(1); // warn } }; +</pre></div></div></td> +<td class="aligned"></td></tr> -A a; -</pre></td><td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.LocalStaticDestroyed -<br>(C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.LocalStaticDestroyed</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: function containing a definition of static local object is called during the destruction of an object with static storage duration so that flow of control passes through the definition of the previously destroyed -static local object -</td><td><pre> +static local object. +<p>Source: C++11 3.6.3p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void f(); class A { @@ -386,70 +446,130 @@ class B {}; A a; void f() { - static B b; // <- -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">undefbehavior.UseAfterRelease -<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> -Pointer to deleted object is referenced (The effect of using an invalid pointer -value is undefined) -</td><td><pre> -#include <stdlib.h> - -void test() { - int *p = new int; - delete p; - int i = *p; // warn + static B b; } +</pre></div></div></td> +<td class="aligned"></td></tr> -</pre></td><td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.ZeroAllocDereference -<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ZeroAllocDereference</span><span class="lang"> +(C, C++)</span><div class="descr"> The effect of dereferencing a pointer returned as a request for zero size is -undefined -</td><td><pre> -#include <stdlib.h> - -int *p = new int[0]; -int i = p[0]; // warn -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">undefbehavior.DeadReferenced -<br>(C++)</span><br><br> +undefined.<br> +Note: possibly an enhancement to <span class="name"> +unix.Malloc</span>. +<p>Source: C++03 3.7.3.1p2; C++11 3.7.4.1p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int *p = malloc(0); +*p = 1; // warn +</pre></div> +<div class="example"><pre> +int *p = new int{}; +int i = *p; // warn +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<!--<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.DeadReferenced</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: the following usage of the pointer to the object whose -lifetime has ended can result in undefined behavior -</td><td><pre> -// C++03 +lifetime has ended can result in undefined behavior. +<p>Source: C++03 3.8p5, p7; C++11 3.8p5, p7.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <new> class A { public: int i; - void f() {}; }; -class B : public A { +class B : public A {}; + +int test() { + B *b = new B; + new(b) A; + return b->i; // warn +} +</pre></div> +<div class="example"><pre> +#include <new> + +class A { +public: + void f() {}; }; +class B : public A {}; + void test() { B *b = new B; new(b) A; - b->i; // warn - b->f(); // warn + b->f(); // warn +} +</pre></div> +<div class="example"><pre> +#include <new> + +class A {}; + +class B : public A {}; + +A* test() { + B *b = new B; + new(b) A; static_cast<A*>(b); // warn +} +</pre></div> +<div class="example"><pre> +#include <new> + +class A {}; + +class B : public A {}; + +A* test() { + B *b = new B; + new(b) A; dynamic_cast<A*>(b); // warn - delete b; // warn } +</pre></div> +<div class="example"><pre> +#include <new> +class A {}; + +class B : public A {}; + +A* test() { + B *b = new B; + new(b) A; + dynamic_cast<A*>(b); // warn +} +</pre></div> +<div class="example"><pre> +#include <new> + +class A {}; + +class B : public A {}; + +void test() { + B *b = new B; + new(b) A; + delete b; // warn +} +</pre></div> +<div class="example"><pre> // C++11 #include <new> class A { public: int i; - void f() {}; }; class B : public A { @@ -457,228 +577,257 @@ public: ~B() {}; }; -void test() { +int test() { A *a = new A; new(a) B; - a->i; // warn - a->f(); // warn - B *b = new B; - new(b) A; - b->i; // warn - b->f(); // warn - static_cast<A*>(b); // warn - dynamic_cast<A*>(b); // warn - delete b; // warn + return a->i; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr>--> -<tr><td><span class="name">undefbehavior.ObjLocChanges -<br>(C++)</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ObjLocChanges</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: the program must ensure that an object occupies the same -storage location when the implicit or explicit destructor call takes place -</td><td><pre> +storage location when the implicit or explicit destructor call takes place. +<p>Source: C++11 3.8p8.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <new> -class T { }; -struct B { +class A {}; + +class B { +public: ~B(); }; void test() { - B *b1 = new B; - B b2; - new (b1) T; - new (&b2) T; - delete b1; // warn + B b; + new (&b) A; } // warn -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +#include <new> + +class A {}; + +class B { +public: + ~B(); +}; + +void test() { + B *b = new B; + new (b) A; + delete b; // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.ExprEvalOrderUndef -<br>(C, C++03)</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ExprEvalOrderUndef</span><span class="lang"> +(C, C++03)</span><div class="descr"> Undefined behavior: a scalar object shall have its stored value modified at -most once by the evaluation of an expression -</td><td><pre> -void test () { +most once by the evaluation of an expression.<br> +Note: most cases are currently handled by the Clang core (search for 'multiple +unsequenced modifications' warning in Clang tests). +<p>Source: C++03 5p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int test () { int i = 0; - int v[1] = {0}; - i = v[i++]; // warn i = ++i + 1; // warn + return i; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.StaticInitReentered -<br>(C)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.StaticInitReentered</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: static declaration is re-entered while the object is being -initialized -</td><td><pre> +initialized. +<p>Source: C++11 6.7p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> int test(int i) { - static int s = test(2*i); // warn - return i+1; + static int s = test(2 * i); // warn + return i + 1; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.ConstModified -<br>(C, C++)</span><br><br> -Undefined behavior: const object is being modified -</td><td><pre> -#include <stdlib.h> -class X { -public : - mutable int i; - int j; -}; -class Y { +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ConstModified</span><span class="lang"> +(C, C++)</span><div class="descr"> +Undefined behavior: const object is being modified. +<p>Source: C++03 7.1.5.1p4, C++11 7.1.6.1p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + const int *cp = new const int (0); + int *p = const_cast<int *>(cp); + *p = 1; // warn + delete p; +} +</pre></div> +<div class="example"><pre> +class C { public : - X x; - Y(); + int i; + C(); }; void test() { - const int *ciq = - (int *)malloc(sizeof(int)); - int *iq = const_cast<int *>(ciq); - *iq = 1; // warn + const C cb; - const Y y; - Y* p = const_cast<Y*>(&y); - p->x.i = 1; // ok - p->x.j = 1; // warn + C* cp = const_cast<C *>(&cb); + cp->i = 1; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.DeadDestructed -<br>(C++)</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.DeadDestructed</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: the destructor is invoked for an object whose lifetime -has ended -</td><td><pre> +has ended. +<p>Source: C++11 12.4p14.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { public: - void f() {}; - A() {}; - ~A() {}; + void f(); + A(); + ~A(); }; void test() { A a; a.~A(); } // warn -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.MethodCallBeforeBaseInit -<br>(C++)</span><br><br> -Undefined behavior: calls member function but base not yet initialized -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.MethodCallBeforeBaseInit</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: calls member function but base not yet initialized. +<p>Source: C++03 12.6.2p8; C++11 12.6.2p13.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { public : - A(int ); + A(int); }; + class B : public A { public : int f(); B() : A(f()) {} // warn }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.MemberOrBaseRefBeforeCtor -<br>(C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.MemberOrBaseRefBeforeCtor</span><span class="lang"> +(C++)</span><div class="descr"> C++ Undefined behavior: non-static member or base class of non-POD class type -is referred before constructor begins execution<br> +is referred before constructor begins execution.<br> C++11 Undefined behavior: non-static member or base class of a class with a -non-trivial constructor is referred before constructor begins execution -</td><td><pre> -// C++03 +non-trivial constructor is referred before constructor begins execution. +<p>Source: C++03 12.7p1; C++11 12.7p1.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +struct non_POD { + int i; + non_POD(); +}; + +extern non_POD non_pod; + +int *p = &non_pod.i; // warn +</pre></div> +<div class="example"><pre> struct POD { int i; }; -struct non_POD : public POD { - int j; +struct non_POD : public POD { POD pod; }; -extern POD pod; extern non_POD non_pod; -int *p1 = &non_pod.j; // warn -int *p2 = &non_pod.pod.i; // warn -int *p3 = &pod.i; // ok -POD *p4 = &non_pod; // warn - -POD a; -non_POD b; - -struct S { - int *k; - non_POD non_pod; - S() : k(&non_pod.j) {} // warn -}; - -// C++11 -struct trivial { +int *p = &non_pod.pod.i; // warn +</pre></div> +<div class="example"><pre> +struct POD { int i; }; -struct non_trivial: public trivial { - non_trivial() {}; - int j; - trivial pod; -}; - -extern trivial t; -extern non_trivial nt; +struct non_POD : public POD {}; -int *p1 = &nt.j; // warn -int *p2 = &nt.i; // warn -int *p3 = &t.i; // ok -trivial *p4 = &nt; +extern non_POD non_pod; -trivial t; -non_trivial nt; +POD *p = &non_pod; // warn +</pre></div> +<div class="example"><pre> +struct non_POD { + int i; + non_POD(); +}; struct S { int *k; - non_trivial nt; - S() : k(&nt.j) {} // warn + non_POD non_pod; + S() : k(&non_pod.i) {} // warn }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.MemberRefAfterDtor -<br>(C++)</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.MemberRefAfterDtor</span><span class="lang"> +(C++)</span><div class="descr"> C++03: Undefined behavior: non-static member of non-POD class type is referred -after destructor ends execution<br> +after destructor ends execution.<br> C++11: Undefined behavior: non-static member of a class with a non-trivial -destructor is referred after destructor ends execution -</td><td><pre> -// C++03 -struct non_POD { - virtual void f() {}; +destructor is referred after destructor ends execution. +<p>Source: C++03 12.7p1; C++11 12.7p1.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +class C { +public: + C(); + void f(); }; void test() { - non_POD *non_pod = new non_POD(); - non_pod->~non_POD(); - non_pod->f(); // warn + C *c = new C(); + c->~C(); + c->f(); // warn } +</pre></div></div></td> +<td class="aligned"></td></tr> -// C++11 -struct S { - ~S() {}; - void f() {}; -}; -void test() { - S *s = new S(); - s->~S(); - s->f(); // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">undefbehavior.CtorForeignCall -<br>(C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.CtorForeignCall</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: call to virtual function of an object under construction -whose type is neither the constructors own class or one of its bases -</td><td><pre> +whose type is neither the constructors own class or one of its bases. +<p>Source: C++11 12.7p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { public: virtual void f() {}; @@ -693,15 +842,47 @@ class C : public A, B { public: C() : B((A*)this) {} }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.CtorForeignCast -undefbehavior.CtorForeignTypeid -<br>(C++)</span><br><br> -Undefined behavior: the operand of typeid/dynamic_cast is an object under +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.CtorForeignTypeid</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: the operand of <code>typeid</code> is an object under construction whose type is neither the constructors own class or one of its -bases -</td><td><pre> +bases. +<p>Source: C++11 12.7p5.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +#include <typeinfo> + +class A {}; + +class B { +public: + B(A* a) { + (void)typeid(*a); // warn + } +}; + +class C : public A, B { +public: + C() : B((A*)this) {} +}; +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.CtorForeignCast</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: the operand of <code>dynamic_cast</code> is an object under +construction whose type is neither the constructors own class or one of its +bases. +<p>Source: C++11 12.7p6.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <typeinfo> class A { @@ -712,8 +893,7 @@ public: class B { public: B(A* a) { - typeid(*a); // warn - dynamic_cast<B*>(a); //warn + (void)dynamic_cast<B*>(a); //warn } }; @@ -721,45 +901,83 @@ class C : public A, B { public: C() : B((A*)this) {} }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.MemberRefInCatch -undefbehavior.BaseRefInCatch -<br>(C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.MemberOrBaseRefInCatch</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor -for that object results in undefined behavior -</td><td><pre> +for that object results in undefined behavior. +<p>Source: C++11 15.3p10.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void f() { throw 1; } + class C { int i; public : C() - try - : i(1) {} - catch (...) - { + try { + f(); + } + catch (...) { + i=2; // warn + } +}; +</pre></div> +<div class="example"><pre> +void f() { throw 1; } + +class Base { +public: + int i; +}; + +class C: public Base { +public : + ~C() try { + f(); + } + catch (...) { i=2; // warn } }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.ReturnAtCatchEnd -<br>(C++)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ReturnAtCatchEnd</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: a function returns when control reaches the end of a -handler. This results in undefined behavior in a value-returning -function -</td><td><pre> +handler. This results in undefined behavior in a value-returning function. +<p>Source: C++11 15.3p10.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void f() { throw 1; } + int test() try { + f(); + return 1; } catch(int) { } // warn -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">undefbehavior.AutoptrsOwnSameObj -<br>(C++03)</span><br><br> -Undefined behavior: if more than one auto_ptr owns the same object at the same -time the behavior of the program is undefined. -</td><td><pre> +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.AutoptrsOwnSameObj</span><span class="lang"> +(C++03)</span><div class="descr"> +Undefined behavior: if more than one <code>auto_ptr</code> owns the same object +at the same time the behavior of the program is undefined. +<p>Source: C++03 20.4.5p3; C++11 <code>auto_ptr</code> is deprecated +(D.10).</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <memory> void test() { @@ -767,71 +985,83 @@ void test() { std::auto_ptr<int> p(data); std::auto_ptr<int> q(data); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.BasicStringOutOfBound</span><span class="lang"> +(C++03)</span><div class="descr"> +Undefined behavior: out-of-bound <code>basic_string</code> access/modification. +<br>Note: possibly an enhancement to <span class="name"> +alpha.security.ArrayBoundV2</span>. +<p>Source: C++03 21.3.4p1; C++11 behavior is defined +(21.4.5p2).</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +#include <string> -<tr><td><span class="name">undefbehavior.BasicStringBoundAccess -<br>(C++03)</span><br><br> -Undefined behavior: out-of-bound basic_string access -</td><td><pre> void test() { std::basic_string<char> s; char c = s[10]; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +#include <string> -<tr><td><span class="name">undefbehavior.BasicStringBoundModification -<br>(C++)</span><br><br> -Undefined behavior: out-of-bound basic_string modification -</td><td><pre> void test() { std::basic_string<char> s; s[10] = 0; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.EosDereference -<br>(C++)</span><br><br> -Undefined behavior: the result of operator*() on an end of stream is -undefined -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.EosDereference</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: the result of <code>operator*()</code> on an end of a +stream is undefined. +<p>Source: C++03 24.5.3p2; C++11 24.6.3p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <vector> -void test() { +int test() { std::vector<int> v; - int i = *v.end(); // warn - *v.end() = 0; // warn + return *v.end(); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.QsortNonPOD -undefbehavior.QsortNonTrivial -<br>C++</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.QsortNonPODNonTrivial</span><span class="lang"> +(C++)</span><div class="descr"> C++03: Undefined behavior: the objects in the array passed to qsort are of -non-POD type<br> +non-POD type.<br> C++11: Undefined behavior: the objects in the array passed to qsort are of -non-trivial type -</td><td><pre> +non-trivial type. +<p>Source: C++03 25.4p4; C++11 25.5p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> // C++03 #include <cstdlib> + struct non_POD { - int i; - non_POD(int ii) : i(ii) {} + non_POD(); }; -non_POD values[] = { non_POD(2), non_POD(1) }; +non_POD values[] = { non_POD(), non_POD() }; -int compare(const void *a, - const void *b) { - return ( (*(non_POD*)a).i - - (*(non_POD*)b).i ); -} +int compare(const void *a, const void *b); void test() { - qsort(values, 2, sizeof(non_POD), - compare); // warn + qsort(values, 2, sizeof(non_POD), compare); // warn } - +</pre></div> +<div class="example"><pre> // C++11 #include <cstdlib> @@ -843,57 +1073,64 @@ struct trivial_non_POD : public S { struct non_trivial { int i; - non_trivial() {} + non_trivial(); }; trivial_non_POD tnp[2]; non_trivial nt[2]; -int compare1(const void *a, - const void *b) { - return ( (*(trivial_non_POD *)a).i - - (*(trivial_non_POD *)b).i ); -} +int compare1(const void *a, const void *b); -int compare2(const void *a, - const void *b) { - return ( (*(non_trivial *)a).i - - (*(non_trivial *)b).i ); -} +int compare2(const void *a, const void *b); void test() { - qsort(tnp, 2, sizeof(trivial_non_POD), - compare1); // ok - qsort(nt, 2, sizeof(non_trivial), - compare2); // warn + qsort(tnp, 2, sizeof(trivial_non_POD), compare1); // ok + qsort(nt, 2, sizeof(non_trivial), compare2); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.ThrowWhileCopy -<br>C++</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ThrowWhileCopy</span><span class="lang"> +(C++)</span><div class="descr"> Undefined behavior: copy constructor/assignment operator can throw an exception. -The effects are undefined if an exception is thrown. -</td><td><pre> -struct S { +The effects are undefined if an exception is thrown.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +class C { +public: int i, j; - S (const S &s) { - i = s.i; + C (const C &c) { + i = c.i; throw 1; // warn - j = s.j; + j = c.j; }; - S &operator=(const S &s) { - i = s.i; +}; +</pre></div> +<div class="example"><pre> +class C { +public: + int i, j; + C &operator=(const C &c) { + i = c.i; throw 1; // warn - j = s.j; - } + j = c.j; + }; }; -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">undefbehavior.ValarrayArgBound -<br>(C++)</span><br><br> -Undefined behavior: the value of the second argument is greater than the number -of values pointed to by the first argument -</td><td><pre> +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ValarrayArgBound</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: the value of the <code><i>n</i></code> argument passed +to <code>valarray</code> constructor is greater than the number of values +pointed to by the first argument (source). +<p>Source: C++03 26.3.2.1p4; C++11 26.6.2.2p4.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <valarray> struct S { @@ -905,88 +1142,133 @@ void test(void) { S s[] = { S(1), S(2) }; std::valarray<S> v(s,3); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.ValarrayLengthDiffer -<br>(C++)</span><br><br> -Undefined behavior: valarray operands are of different length -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ValarrayLengthDiffer</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: <code>valarray</code> operands are of different length. +<p>Source: C++03 26.3.2.2p1, 26.3.2.6p3, 26.3.3.1p3, 26.3.3.2p3; +C++11 defined (26.6.2.3p1), 26.6.2.7p3, 26.6.3.1p3, +26.6.3.2p3.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> // C++03 #include <valarray> void test(void) { std::valarray<int> a(0, 1), b(0, 2); - std::valarray<bool> c(false, 1); a = b; // warn - a *= b; // warn - a = a * b; // warn - c = a == b; // warn b.resize(1); - a = b; // OK + a = b; // ok +} +</pre></div> +<div class="example"><pre> +// C++03, C++11 +#include <valarray> + +void test(void) { + std::valarray<int> a(0, 1), b(0, 2); + a *= b; // warn } +</pre></div> +<div class="example"><pre> +// C++03, C++11 +#include <valarray> -// C++11 +void test(void) { + std::valarray<int> a(0, 1), b(0, 2); + a = a + b; // warn +} +</pre></div> +<div class="example"><pre> +// C++03, C++11 #include <valarray> void test(void) { std::valarray<int> a(0, 1), b(0, 2); std::valarray<bool> c(false, 1); - a = b; // ok - a *= b; // ok - a = a * b; // warn c = a == b; // warn - b.resize(1); - a = b; // OK } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.ValarrayZeroLength -<br>(C++)</span><br><br> -Undefined behavior: calling sum()/min()/max() method of an array having zero -length, the behavior is undefined -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ValarrayZeroLength</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: calling <code>sum()</code>/<code>min()</code>/<code> +max()</code> methods of a zero length <code>valarray<code> the behavior is +undefined. +<p>Source: C++03 26.3.2.7p2, p3, p4; C++11 26.6.2.8p5, p6, +p7.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <valarray> void test(void) { std::valarray<int> v(0, 0); v.sum(); // warn - v.min(); // warn - v.max(); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.ValarrayBadIndirection -<br>(C++)</span><br><br> -Undefined behavior: element N is specified more than once in the -indirection -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.ValarrayBadIndirection</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: element is specified more than once in an indirection. +<p>Source: C++03 26.3.9.2p2, 26.3.9.3p2; C++11 26.6.9.2p2, +26.6.9.3p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <valarray> void test() { - size_t addr[] = {0, 1, 1}; // N is 1 + // '1' is specified more then once + size_t addr[] = {0, 1, 1}; std::valarray<size_t>indirect(addr, 3); std::valarray<int> a(0, 5), b(1, 3); a[indirect] = b; //warn +} +</pre></div> +<div class="example"><pre> +#include <valarray> + +void test() { + // '1' is specified more then once + size_t addr[] = {0, 1, 1}; + std::valarray<size_t>indirect(addr, 3); + std::valarray<int> a(0, 5), b(1, 3); a[indirect] *= b; //warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">undefbehavior.IosBaseDestroyedBeforeInit -<br>(C++)</span><br> -<br>Undefined behavior: ios_base object is destroyed before initialization have -taken place. basic_ios::init should be call to initialize ios_base -members -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.IosBaseDestroyedBeforeInit</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: <code>ios_base</code> object is destroyed before +initialization have taken place. <code>basic_ios::init</code> should be call to +initialize <code>ios_base</code> members. +<p>Source: C++03 27.4.2.7p1, 27.4.4.1p2; C++11 27.5.3.7p1, +27.5.5.2p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <ios> using namespace std; -template <class T, class Traits = std::char_traits<T>> +template <class T, class Traits = std::char_traits<T> > class my_stream1 : public std::basic_ios<T, Traits> { }; -template <class T, class Traits = std::char_traits<T>> +template <class T, class Traits = std::char_traits<T> > class my_stream2 : public std::basic_ios<T, Traits> { - class my_streambuf : public std::basic_streambuf<T, Traits> { + class my_streambuf + : public std::basic_streambuf<T, Traits> { }; public: my_stream2() { @@ -995,28 +1277,35 @@ public: }; void test() { - my_stream1<char> *p1 = new my_stream1<char> - my_stream2<char> *p2 = new my_stream2<char> + my_stream1<char> *p1 = new my_stream1<char>; + my_stream2<char> *p2 = new my_stream2<char>; delete p1; // warn delete p2; // ok } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.IosBaseUsedBeforeInit -<br>(C++11)</span><br><br> -Undefined behavior: ios_base object is used before initialization have taken -place. basic_ios::init should be call to initialize ios_base members -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.IosBaseUsedBeforeInit</span><span class="lang"> +(C++11)</span><div class="descr"> +Undefined behavior: <code>ios_base</code> object is used before initialization +have taken place. <code>basic_ios::init</code> should be call to +initialize <code>ios_base</code> members. +<p>Source: C++11 27.5.3.7p1, 27.5.5.2p2.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <ios> using namespace std; -template <class T, class Traits = std::char_traits<T>> +template <class T, class Traits = std::char_traits<T> > class my_stream1 : public std::basic_ios<T, Traits> { }; -template <class T, class Traits = std::char_traits<T>> +template <class T, class Traits = std::char_traits<T> > class my_stream2 : public std::basic_ios<T, Traits> { - class my_streambuf : public std::basic_streambuf<T, Traits> { + class my_streambuf + : public std::basic_streambuf<T, Traits> { }; public: my_stream2() { @@ -1025,20 +1314,24 @@ public: }; void test() { - my_stream1<char> *p1 = new my_stream1<char> - my_stream2<char> *p2 = new my_stream2<char> + my_stream1<char> *p1 = new my_stream1<char>; + my_stream2<char> *p2 = new my_stream2<char>; p1->narrow('a', 'b'); // warn p2->narrow('a', 'b'); // ok - delete p1; // warn - delete p2; // ok } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">undefbehavior.MinusOnePosType -<br>(C++)</span><br><br> -Undefined behavior: passing -1 to any streambuf/istream/ostream member that -accepts a value of type traits::pos_type result in undefined behavior -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +undefbehavior.MinusOnePosType</span><span class="lang"> +(C++)</span><div class="descr"> +Undefined behavior: passing -1 to any <code>streambuf</code>/<code> +istream</code>/<code>ostream</code> member that accepts a value of +type <code>traits::pos_type</code> result in undefined behavior. +<p>Source: C++03 27.4.3.2p3; C++11 27.5.4.2p3.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <fstream> class my_streambuf : public std::streambuf { @@ -1046,16 +1339,19 @@ class my_streambuf : public std::streambuf { seekpos(-1); // warn } }; +</pre></div> +<div class="example"><pre> +#include <fstream> void test() { std::filebuf fb; std::istream in(&fb); - std::ostream out(&fb); std::filebuf::off_type pos(-1); in.seekg(pos); // warn - out.seekp(-1); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + </table> <!-- ============================ different ================================ --> @@ -1065,409 +1361,505 @@ void test() { <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr> </thead> -<tr><td><span class="name">different.ArgEvalOrderUndef -<br>(C)</span><br><br> -Errors because of the order of evaluation of function arguments is undefined -</td><td><pre> -void f(int, int); - -void test() { - int i = 0; - int v[1] = {0}; - f(v[i], i++); // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">different.FuncPtrInsteadOfCall -<br>(C)</span><br><br> -Possibly a function call should be used instead of a pointer to function -</td><td><pre> -int f(); - -void test() { - if (f == 0) {} // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">SuccessiveAssign -<br>(C)</span><br><br> -Successive assign to a variable -</td><td><pre> -void test() { - int i=0; +<tr><td><div class="namedescr expandable"><span class="name"> +different.SuccessiveAssign</span><span class="lang"> +(C)</span><div class="descr"> +Successive assign to a variable.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int test() { + int i; i=1; i=2; // warn + return i; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.NullDerefStmtOrder -<br>enhancement to core.NullDereference<br>(C)</span><br><br> + +<tr><td><div class="namedescr expandable"><span class="name"> +different.NullDerefStmtOrder</span><span class="lang"> +(C)</span><div class="descr"> Dereferencing of the null pointer might take place. Checking the pointer for -null should be performed first -</td><td><pre> +null should be performed first. +<br>Note: possibly an enhancement to <span class="name"> +core.NullDereference</span>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> struct S { int x; }; -S* f(); +struct S* f(); void test() { - S *p1 = f(); + struct S *p1 = f(); int x1 = p1->x; // warn if (p1) {}; - S *p2 = f(); + struct S *p2 = f(); int x2 = p2->x; // ok } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.NullDerefCondOrder -<br>enhancement to core.NullDereference<br>(C)</span><br><br> +<tr><td><div class="namedescr expandable"><span class="name"> +different.NullDerefCondOrder</span><span class="lang"> +(C)</span><div class="descr"> Dereferencing of the null pointer might take place. Checking the pointer for -null should be performed first -</td><td><pre> -struct S{bool b;}; +null should be performed first. +<br>Note: possibly an enhancement to <span class="name"> +core.NullDereference</span>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +struct S {int i;}; -S* f(); +struct S* f(); void test() { - S *p = f(); - if (p->b && p) {}; // warn + struct S *p = f(); + if (p->i && p) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.MultipleAccessors -<br>(C++)</span><br><br> -multiple accessors met for 'class::field' -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.MultipleAccessors</span><span class="lang"> +(C++)</span><div class="descr"> +Identical accessor bodies. Possibly a misprint.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { int i; int j; public: int getI() { return i; } int getJ() { return i; } // warn +}; +</pre></div> +<div class="example"><pre> +class A { + int i; + int j; +public: void setI(int& ii) { i = ii; } void setJ(int& jj) { i = jj; } // warn }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.AccessorsForPublic -<br>(C++)</span><br><br> -Accessors exist for 'class::field'. Should this field really be public? -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.AccessorsForPublic</span><span class="lang"> +(C++)</span><div class="descr"> +Accessors exist for a public class field. Should this field really be +public?</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> class A { public: int i; // warn int getI() { return i; } void setI(int& ii) { i = ii; } }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.LibFuncResultUnised -<br>(C, C++)</span><br><br> -Calling 'f' ignoring its return value is of no use (* create the list of known -system/library/API functions falling into this category) -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +different.LibFuncResultUnised</span><span class="lang"> +(C, C++)</span><div class="descr"> +Calling a function ignoring its return value is of no use (create the list of +known system/library/API functions falling into this category).</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <vector> void test() { std::vector<int> v; v.empty(); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.WrongVarForStmt -<br>(C, C++)</span><br><br> -Possibly wrong variable is used in the loop/cond-expression of the 'for' -statement. Did you mean 'proper_variable_name'? -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.WrongVarForStmt</span><span class="lang"> +(C, C++)</span><div class="descr"> +Wrong variable is possibly used in the loop/cond-expression of +the <code>for</code> statement. Did you mean +'proper_variable_name'?</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test() { - int i; - int j; - for (j=0; j<3; ++i); // warn - for (int j=0; i<3; ++j); // warn + int i = 0; + int j = 0; + for (i = 0; i < 3; j += 1); // warn +} +</pre></div> +<div class="example"><pre> +void test() { + int i = 0; + int j = 0; + for (int j = 0; i < 3; ++j); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.FloatingCompare -<br>(C)</span><br><br> -Comparing floating point numbers may be not precise -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.FloatingCompare</span><span class="lang"> +(C)</span><div class="descr"> +Comparing floating point numbers may be not precise.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <math.h> -void test() { +double test() { double b = sin(M_PI / 6.0); if (b == 0.5) // warn b = 0; + return b; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.BoolCompare -<br>maybe merge with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> -Comparing boolean to a value other then 0 or 1 -</td><td><pre> -void test() { - int i; - if (0 < i < 3) {}; // warn - bool b; - if (b == 3) {}; // warn -} -</pre></td><td class="aligned"></td></tr> -<tr><td><span class="name">different.BitwiseOpBoolArg -<br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> -bool value is used at the left/right part of the & (|) operator. Did you mean -&& (||) ? -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.BitwiseOpBoolArg</span><span class="lang"> +(C, C++)</span><div class="descr"> +Boolean value met at the left/right part of the bitwise <code>&</code> +or <code>|</code> operator. +Did you mean <code>&&</code> (<code>||</code>) ?</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> int f(); void test() { bool b = true; if (b & f()) {} // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.LabelInsideSwitch -<br>(C)</span><br><br> -Possible misprint: label found inside the switch() statement. (* did you mean -'default'?) -</td><td><pre> -void test() { - int c = 7; + +<tr><td><div class="namedescr expandable"><span class="name"> +different.LabelInsideSwitch</span><span class="lang"> +(C)</span><div class="descr"> +Possibly a misprint: label found inside a <code>switch()</code> +statement.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(int c) { switch(c){ case 1: c += 1; break; - defalt: // warn + defalt: // warn (did you mean 'default'?) c -= 1; break; } } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.IdenticalCondIfIf -<br>(C)</span><br><br> -The conditions of two subsequent 'if' statements are identical -</td><td><pre> -void test() { - int c = 7; - if (c > 5) // <- + +<tr><td><div class="namedescr expandable"><span class="name"> +different.IdenticalCondIfIf</span><span class="lang"> +(C)</span><div class="descr"> +The conditions of two subsequent <code>if</code> statements are +identical.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +int test(int c) { + if (c > 5) c += 1; if (c > 5) // warn c -= 1; + return c; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.LogicalOpUselessArg -<br>(C)</span><br><br> -The second operand of the && operator has no impact on expression result -</td><td><pre> -void test() { - unsigned a; + +<tr><td><div class="namedescr expandable"><span class="name"> +different.LogicalOpUselessArg</span><span class="lang"> +(C)</span><div class="descr"> +The second operand of a <code>&&</code> operator has no impact on +expression result.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test(unsigned a) { if (a<7 && a<10) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.SameResLogicalExpr -<br>(C)</span><br><br> -The expression always evaluates to true/false -</td><td><pre> -void test() { - int i=0; - if (i!=0) {}; // warn - if (i==0 && i==1) {}; // warn - if (i<0 || i>=0) {}; // warn -} -</pre></td><td class="aligned"></td></tr> -<tr><td><span class="name">different.SameResUnsignedCmp -<br>(C)</span><br><br> -Comparison of unsigned expression 'op expr' is always true/false -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.SameResLogicalExpr</span><span class="lang"> +(C)</span><div class="descr"> +An expression is always evaluated to true/false.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test() { - unsigned u; - if (u < -1) {}; // warn - if (u >= 0) {}; // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">different.OpPrecedenceAssignCmp -<br>(C)</span><br><br> -Comparison operation has higher precedence then assignment. Bool value is -assigned to variable of type 'type'. Parenthesis may bee required around an -assignment -</td><td><pre> + int i = 0; + if (i != 0) {}; // warn +} +</pre></div> +<div class="example"><pre> +void test(int i) { + if (i == 0 && i == 1) {}; // warn +} +</pre></div> +<div class="example"><pre> +void test(int i) { + if (i < 0 || i >= 0) {}; // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +different.OpPrecedenceAssignCmp</span><span class="lang"> +(C, C++)</span><div class="descr"> +Comparison operation has higher precedence then assignment. Boolean value is +assigned to a variable of other type. Parenthesis may bee required around an +assignment.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> int f(); -void test() { +void test(int x, int y) { bool b; - int x, y; if((b = x != y)) {} // ok if((x = f() != y)) {} // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.OpPrecedenceIifShift -<br>(C)</span><br><br> -?: has lower precedence then << -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.OpPrecedenceIifShift</span><span class="lang"> +(C, C++)</span><div class="descr"> +<code>?:</code> has lower precedence then <code><<</code>. +<p>Source: Stephen C. Dewhurst "C++ Gotchas: Avoiding Common Problems in Coding +and Design", advise 15.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <iostream> -void test() { - int a; +void test(int a) { std::cout << a ? "a" : "b"; // warn - a << a>7 ? 1 : 2; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +void test(int a) { + a << a > 7 ? 1 : 2; // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.ObjectUnused -<br>(C++)</span><br><br> -The object was created but is not being used<br><br> -The exception object was created but is not being used. Did you mean -'throw std::exception();'? -</td><td><pre> -#include <exception> +<tr><td><div class="namedescr expandable"><span class="name"> +different.ObjectUnused</span><span class="lang"> +(C++)</span><div class="descr"> +The object was created but is not being used.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> struct S { int x, y; - S(int xx, int yy) : x(xx), y(yy) { - } + S(int xx, int yy) : x(xx), y(yy) {} S(int xx) { S(xx, 0); // warn } }; +</pre></div> +<div class="example"><pre> +#include <exception> void test() { - S(0, 0); // warn - std::exception(); // warn + std::exception(); + // warn (did you mean 'throw std::exception()'?) } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.StaticArrayPtrCompare -<br>(C)</span><br><br> -Pointer to static array is being compared to NULL. May the subscripting is -missing -</td><td><pre> -void test() { - int a1[1]; - if (a1 == 0) {}; // warn - int a2[1][1]; - if (a2[0]) {}; // warn +<tr><td><div class="namedescr expandable"><span class="name"> +different.StaticArrayPtrCompare</span><span class="lang"> +(C)</span><div class="descr"> +Pointer to static array is being compared to NULL. May the subscripting is +missing.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +void test() { + int a[1][1]; + if (a[0] == 0) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.ConversionToBool -<br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> -Odd implicit conversion from 'type' to 'bool' -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +different.ConversionToBool</span><span class="lang"> +(C, C++)</span><div class="descr"> +Odd implicit conversion to boolean. +<br>Note: possibly merge with <span class="name"> +alpha.core.BoolAssignment</span>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> bool test() { return 1.; // warn +} +</pre></div> +<div class="example"><pre> +bool test() { return ""; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.ArrayBound -<br>enhancement to experimental.security.ArrayBound[v2]<br>(C, C++)</span><br><br> -Out-of-bound dynamic array access -</td><td><pre> -#include <stdlib.h> +<tr><td><div class="namedescr expandable"><span class="name"> +different.ArrayBound</span><span class="lang"> +(C++)</span><div class="descr"> +Out-of-bound dynamic array access. +<br>Note: possibly an enhancement to <span class="name"> +alpha.security.ArrayBoundV2</span>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test() { - int *p2 = new int[1]; - if(p2[1]) {}; // warn + int *p = new int[1]; int i = 1; - if(p2[i]) {}; // warn + if(p[i]) {}; // warn + delete[] p; } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.StrcpyInputSize -<BR>enhancement to experimental.unix.cstring.OutOfBounds<br>(C)</span><br><br> -Buffer copy without checking size of input -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.StrcpyInputSize</span><span class="lang"> +(C)</span><div class="descr"> +Buffer copy without checking the size of input. +<br>Note: possibly an enhancement to <span class="name"> +alpha.unix.cstring.OutOfBounds</span>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> void test(char* string) { char buf[24]; strcpy(buf, string); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + -<tr><td><span class="name">different.IntegerOverflow -<br>(C)</span><br><br> -Integer overflow -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +different.IntegerOverflow</span><span class="lang"> +(C)</span><div class="descr"> +Integer overflow. +<br>Note: partially handled by Clang core +(search for 'overflow in expression' warning in Clang tests). +<p>Source: <a href="http://cwe.mitre.org/data/definitions/190.html"> +CWE-190</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <limits.h> -int f(int x) { - return INT_MAX+1; // warn -} +int f(int x); void test() { - int x = INT_MAX+1; // warn - f(INT_MAX+1); // warn - - int y = INT_MAX/2+1; // warn - x = y*2; // warn + f(INT_MAX + 1); // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +#include <limits.h> -<tr><td><span class="name">different.SignExtension -<br>(C)</span><br><br> -Unexpected sign extension might take place -</td><td><pre> +int test() { + int x = INT_MAX / 2 + 1; + return x * 2; // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +different.SignExtension</span><span class="lang"> +(C)</span><div class="descr"> +Unexpected sign extension might take place. +<p>Source: <a href="http://cwe.mitre.org/data/definitions/194.html"> +CWE-194</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +unsigned long long test(long long sll) { + unsigned long long ull = sll; // warn + return ull; +} +</pre></div> +<div class="example"><pre> void f(unsigned int i); -int g(); -unsigned int test() { - long long sll; - unsigned long long ull = sll; // warn - long sl; - unsigned long ul = sl; // warn - int si; - unsigned int ui = si; // warn - short ss; - unsigned short us = ss; // warn - signed char sc; - unsigned char uc = sc; // warn +void test(int si) { f(si); // warn - ui = g(); // warn - return si; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div> +<div class="example"><pre> +unsigned int test(int i) { + return i; +} +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">different.NumericTruncation -<br>(C)</span><br><br> -Numeric truncation might take place -</td><td><pre> -void f(int i); -int g(); -int test() { - unsigned long long ull; - long long sll; +<tr><td><div class="namedescr expandable"><span class="name"> +different.NumericTruncation</span><span class="lang"> +(C)</span><div class="descr"> +Numeric truncation might take place. +<p>Source: <a href="http://cwe.mitre.org/data/definitions/197.html"> +CWE-197</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +unsigned long test(unsigned long long ull) { unsigned long ul = ull; // warn - long sl = sll; // warn - unsigned int ui = ul; // warn - int si = sl; // warn - unsigned short us = ui; // warn - short ss = si; // warn - unsigned char uc = us; // warn - signed char sc = uc; // warn + return ul; +} +</pre></div> +<div class="example"><pre> +void f(int i); + +void test(long long sll) { f(sll); // warn - ss = g(); // warn - return sll; // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">different.MissingCopyCtorAssignOp -<br>(C, C++)</span><br><br> -The class has dynamically allocated data members but do not define a copy -constructor/assignment operator -</td><td><pre> -class C { // warn - int *p; // <- +} +</pre></div> +<div class="example"><pre> +int f(); + +short test(long long sll) { + short ss = f(); + return ss; +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +different.MissingCopyCtorAssignOp</span><span class="lang"> +(C++)</span><div class="descr"> +A class has dynamically allocated data members but do not define a copy +constructor/assignment operator. +<p>Source: Scott Meyers "Effective C++", item 11: Prevent exceptions from +leaving destructors.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +class C { + int *p; // warn public: C() { p = new int; } ~C() { delete p; } }; -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> </table> @@ -1477,57 +1869,73 @@ public: <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">WinAPI.CreateProcess -<br>(C)</span><br><br> -After calling CreateProcess(), ensure that process and thread handles get closed -(* for the given example: examine data flow from pi, pi.hProcess and pi.hThread) -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +WinAPI.CreateProcess</span><span class="lang"> +(C)</span><div class="descr"> +<code>CreateProcess()</code>: if the first parameter <code><i> +lpApplicationName</i></code> is NULL then the executable name must be in the +white space-delimited string pointed to by <code><i>lpCommandLine</code></i>. +If the executable or path name has a space in it, there is a risk that a +different executable could be run because of the way the function parses +spaces. +<p>Source: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx"> +MSDN: CreateProcess function, Security Remarks</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <windows.h> void test() { STARTUPINFO si; PROCESS_INFORMATION pi; - BOOL fSuccess; - fSuccess = CreateProcess( - NULL, TEXT("MyProgram.exe"), NULL, NULL, - TRUE, 0, NULL, NULL, &si, &pi); -} // warn -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">WinAPI.LoadLibrary -<br>(C)</span><br><br> -Calling LoadLibrary without a fully qualified path may allow to load a DLL from -arbitrary location -</td><td><pre> + CreateProcess(NULL, TEXT("C:\\Program Files\\App -L -S"), + NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +WinAPI.LoadLibrary</span><span class="lang"> +(C)</span><div class="descr"> +The <code>SearchPath()</code> function is used to retrieve a path to a DLL for +a subsequent <code>LoadLibrary()</code> call. +<p>Source: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx"> +MSDN: LoadLibrary function, Security Remarks</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <windows.h> -void test() { - HINSTANCE h = LoadLibrary("X.dll"); // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">WinAPI.WideCharToMultiByte -<br>(C)</span><br><br> -Buffer overrun while calling WideCharToMultiByte -</td><td><pre> +HINSTANCE test() { + char filePath[100]; + SearchPath(NULL, "file.dll", NULL, 100, filePath, NULL); + return LoadLibrary(filePath); // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +WinAPI.WideCharToMultiByte</span><span class="lang"> +(C)</span><div class="descr"> +Buffer overrun while calling <code>WideCharToMultiByte()</code>. The size of +the input buffer equals the number of characters in the Unicode string, while +the size of the output buffer equals the number of bytes. +<p>Source: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130%28v=vs.85%29.aspx"> +MSDN: WideCharToMultiByte function</a>.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <windows.h> -void test() -{ +void test() { wchar_t ws[] = L"abc"; char s[3]; - int res1 = WideCharToMultiByte( - CP_UTF8, 0, ws, -1, s, - 3, NULL, NULL); // warn - int res2 = WideCharToMultiByte( - CP_UTF8, 0, ws, -1, s, - 3, NULL, NULL); // ok - if (res2 == sizeof(s)) - s[res2-1] = 0; - else - s[res2] = 0; -} -</pre></td><td class="aligned"></td></tr> + WideCharToMultiByte(CP_UTF8, 0, ws, -1, s, + 3, NULL, NULL); // warn +} +</pre></div></div></td> +<td class="aligned"></td></tr> + </table> @@ -1537,25 +1945,30 @@ void test() <col class="namedescr"><col class="example"><col class="progress"> <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> -<tr><td><span class="name">optimization.PassConstObjByValue -<br>(C, C++)</span><br><br> -Optimization: It is more effective to pass const n-th parameter by reference to -avoid unnecessary object copying -</td><td><pre> -struct A { - int a[20]; - int b; -}; - -bool FirstIsZero(const struct A a) { // warn - return a.a[0] == 0; -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">optimization.PostfixIncIter -<br>(C++)</span><br><br> -Optimization: It is more effective to use prefix ++ with iterator here -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +optimization.PassConstObjByValue</span><span class="lang"> +(C, C++)</span><div class="descr"> +Optimization: It is more effective to pass constant parameter by reference to +avoid unnecessary object copying.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +struct A {}; + +void f(const struct A a); // warn +</pre></div></div></td> +<td class="aligned"></td></tr> + + +<tr><td><div class="namedescr expandable"><span class="name"> +optimization.PostfixIncIter</span><span class="lang"> +(C++)</span><div class="descr"> +Optimization: It is more effective to use prefix increment operator with +iterator. +<p>Source: Scott Meyers "More Effective C++", item 6: +Distinguish between prefix and postfix forms of increment and decrement +operators.</p></div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <vector> void test() { @@ -1564,41 +1977,35 @@ void test() { for(it = v.begin(); it != v.end(); it++) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">optimization.MultipleCallsStrlen -<br>(C)</span><br><br> -Optimization: multiple calls to strlen for a given string in the given -expression. It is more effective to hold strlen result in a temporary -variable -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +optimization.MultipleCallsStrlen</span><span class="lang"> +(C)</span><div class="descr"> +Optimization: multiple calls to <code>strlen()</code> for a string in an +expression. It is more effective to hold a value returned +from <code>strlen()</code> in a temporary variable.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <string.h> -void test() { - const char* s = "abc"; +void test(const char* s) { if (strlen(s) > 0 && strlen(s) < 7) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">optimization.EmptyCstrDetect -<br>(C)</span><br><br> -Optimization: it is more efficient to use "str[0] != '\0'" to identify an empty -string -</td><td><pre> -#include <string.h> -void test() { - const char* s = "abc"; - if (strlen(s) > 0) {}; // warn -} -</pre></td><td class="aligned"></td></tr> - -<tr><td><span class="name">optimization.StrLengthCalculation -<br>(C, C++)</span><br><br> -Optimization: it is more efficient to use string::length() method to calculate -string length -</td><td><pre> +<tr><td><div class="namedescr expandable"><span class="name"> +optimization.StrLengthCalculation</span><span class="lang"> +(C++)</span><div class="descr"> +Optimization: it is more efficient to use <code>string::length()</code> to +calculate the length of an <code>std::string</code>.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <string> #include <string.h> @@ -1606,20 +2013,26 @@ void test() { std::string s; if (strlen(s.c_str()) != 0) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> -<tr><td><span class="name">optimization.EmptyContainerDetect -<br>(C, C++)</span><br><br> -Optimization: It is more efficient to use container.empty() to identify an -empty container -</td><td><pre> + +<tr><td><div class="namedescr expandable"><span class="name"> +optimization.EmptyContainerDetect</span><span class="lang"> +(C++)</span><div class="descr"> +Optimization: It is more efficient to use containers <code>empty()</code> +method to identify an empty container.</div></div></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> #include <list> void test() { std::list<int> l; if (l.size() != 0) {}; // warn } -</pre></td><td class="aligned"></td></tr> +</pre></div></div></td> +<td class="aligned"></td></tr> + </table> |