summaryrefslogtreecommitdiffstats
path: root/www
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2014-04-29 00:46:17 +0000
committerJordan Rose <jordan_rose@apple.com>2014-04-29 00:46:17 +0000
commit0dae3637124de2596d666d0b7df31b11185ee201 (patch)
tree3e1914016b8735d9531f3da7a4dc5a57b9770c0f /www
parenta172a34fb1b047c946366af60eb7e5da2ac32f4c (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.html1400
-rw-r--r--www/analyzer/content.css32
-rw-r--r--www/analyzer/potential_checkers.html2185
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-&gt;f(); // warn: object pointer is uninitialized
+}
+</pre></div>
+<div class="example"><pre>
+// C++
+class C {
+public:
+ void f();
+};
+
+void test() {
+ C *pc = 0;
+ pc-&gt;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-&gt;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 = &amp;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-&gt;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 &amp;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(&amp;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, &amp;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, &amp;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, &amp;outData);
+
+ st = SecKeychainItemCopyContent(2, ptr, ptr, length, &amp;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, &amp;attrList,
+ length, &amp;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, &amp;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, &amp;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,
+ &amp;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(&amp;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 &lt;typename T&gt;
+struct SimpleSmartPointer {
+ T *ptr;
+
+ explicit SimpleSmartPointer(T *p = 0) : ptr(p) {}
+ ~SimpleSmartPointer() {
+ delete ptr; // warn
+ }
+};
+
+void test() {
+ SimpleSmartPointer&lt;int&gt; 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 &lt;stdlib.h&gt;
-
-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 &lt;stdlib.h&gt;
+<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 &lt;stdlib.h&gt;
-
-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 &lt;stdlib.h&gt;
-
-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 &lt;string.h&gt;
-
+ // 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 &lt;stdlib.h&gt;
+<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 &lt;stdarg.h&gt;
void test(int x, ...) {
va_list args;
int y = va_arg(args, int); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+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 &lt;stdarg.h&gt;
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&lt;T[]&gt; 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&lt;<i>type</i>[]&gt;</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 &lt;stdlib.h&gt;
#include &lt;memory&gt;
void test() {
std::auto_ptr&lt;int&gt; p1(new int); // Ok
std::auto_ptr&lt;int&gt; p2(new int[3]); // warn
- std::auto_ptr&lt;int&gt;
- p3((int *)malloc(sizeof(int))); // warn
}
-</pre></td><td class="aligned"></td></tr>
+</pre></div>
+<div class="example"><pre>
+#include &lt;stdlib.h&gt;
+#include &lt;memory&gt;
+
+void test() {
+ std::auto_ptr&lt;int&gt; 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 &lt;stdlib.h&gt;
int readWrapper(int fd, int *count) {
int lcount = read(fd, globalBuf, sizeof(globalBuf));
- if (lcount &lt; 0)
+ if (lcount < 0)
return errno;
*count = lcount;
return 0;
@@ -338,7 +391,8 @@ void use(int fd) {
if (!readWrapper(fd, &amp;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 &lt;cstdlib&gt;
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; // &lt;-
-}
-</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 &lt;stdlib.h&gt;
-
-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 &lt;stdlib.h&gt;
-
-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 &lt;new&gt;
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-&gt;i; // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;new&gt;
+
+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-&gt;f(); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;new&gt;
+
+class A {};
+
+class B : public A {};
+
+A* test() {
+ B *b = new B;
+ new(b) A;
static_cast&lt;A*&gt;(b); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;new&gt;
+
+class A {};
+
+class B : public A {};
+
+A* test() {
+ B *b = new B;
+ new(b) A;
dynamic_cast&lt;A*&gt;(b); // warn
- delete b; // warn
}
+</pre></div>
+<div class="example"><pre>
+#include &lt;new&gt;
+class A {};
+
+class B : public A {};
+
+A* test() {
+ B *b = new B;
+ new(b) A;
+ dynamic_cast&lt;A*&gt;(b); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;new&gt;
+
+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 &lt;new&gt;
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&lt;A*&gt;(b); // warn
- dynamic_cast&lt;A*&gt;(b); // warn
- delete b; // warn
+ return a-&gt;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 &lt;new&gt;
-class T { };
-struct B {
+class A {};
+
+class B {
+public:
~B();
};
void test() {
- B *b1 = new B;
- B b2;
- new (b1) T;
- new (&amp;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 &lt;new&gt;
+
+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 &lt;stdlib.h&gt;
-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&lt;int *&gt;(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&lt;int *&gt;(ciq);
- *iq = 1; // warn
+ const C cb;
- const Y y;
- Y* p = const_cast&lt;Y*&gt;(&amp;y);
- p-&gt;x.i = 1; // ok
- p-&gt;x.j = 1; // warn
+ C* cp = const_cast&lt;C *&gt;(&cb);
+ cp-&gt;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 = &amp;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 = &amp;non_pod.j; // warn
-int *p2 = &amp;non_pod.pod.i; // warn
-int *p3 = &amp;pod.i; // ok
-POD *p4 = &amp;non_pod; // warn
-
-POD a;
-non_POD b;
-
-struct S {
- int *k;
- non_POD non_pod;
- S() : k(&amp;non_pod.j) {} // warn
-};
-
-// C++11
-struct trivial {
+int *p = &amp;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 = &amp;nt.j; // warn
-int *p2 = &amp;nt.i; // warn
-int *p3 = &amp;t.i; // ok
-trivial *p4 = &amp;nt;
+extern non_POD non_pod;
-trivial t;
-non_trivial nt;
+POD *p = &amp;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(&amp;nt.j) {} // warn
+ non_POD non_pod;
+ S() : k(&amp;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-&gt;~C();
+ c-&gt;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 &lt;typeinfo&gt;
+
+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 &lt;typeinfo&gt;
class A {
@@ -712,8 +893,7 @@ public:
class B {
public:
B(A* a) {
- typeid(*a); // warn
- dynamic_cast&lt;B*&gt;(a); //warn
+ (void)dynamic_cast&lt;B*&gt;(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 &lt;memory&gt;
void test() {
@@ -767,71 +985,83 @@ void test() {
std::auto_ptr&lt;int&gt; p(data);
std::auto_ptr&lt;int&gt; 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 &lt;string&gt;
-<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&lt;char&gt; s;
char c = s[10]; // warn
}
-</pre></td><td class="aligned"></td></tr>
+</pre></div>
+<div class="example"><pre>
+#include &lt;string&gt;
-<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&lt;char&gt; 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 &lt;vector&gt;
-void test() {
+int test() {
std::vector&lt;int&gt; 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 &lt;cstdlib&gt;
+
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 &lt;cstdlib&gt;
@@ -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 &amp;s) {
- i = s.i;
+ C (const C &amp;c) {
+ i = c.i;
throw 1; // warn
- j = s.j;
+ j = c.j;
};
- S &amp;operator=(const S &amp;s) {
- i = s.i;
+};
+</pre></div>
+<div class="example"><pre>
+class C {
+public:
+ int i, j;
+ C &amp;operator=(const C &amp;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 &lt;valarray&gt;
struct S {
@@ -905,88 +1142,133 @@ void test(void) {
S s[] = { S(1), S(2) };
std::valarray&lt;S&gt; 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 &lt;valarray&gt;
void test(void) {
std::valarray&lt;int&gt; a(0, 1), b(0, 2);
- std::valarray&lt;bool&gt; 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 &lt;valarray&gt;
+
+void test(void) {
+ std::valarray&lt;int&gt; a(0, 1), b(0, 2);
+ a *= b; // warn
}
+</pre></div>
+<div class="example"><pre>
+// C++03, C++11
+#include &lt;valarray&gt;
-// C++11
+void test(void) {
+ std::valarray&lt;int&gt; a(0, 1), b(0, 2);
+ a = a + b; // warn
+}
+</pre></div>
+<div class="example"><pre>
+// C++03, C++11
#include &lt;valarray&gt;
void test(void) {
std::valarray&lt;int&gt; a(0, 1), b(0, 2);
std::valarray&lt;bool&gt; 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 &lt;valarray&gt;
void test(void) {
std::valarray&lt;int&gt; 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 &lt;valarray&gt;
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&lt;size_t&gt;indirect(addr, 3);
std::valarray&lt;int&gt; a(0, 5), b(1, 3);
a[indirect] = b; //warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;valarray&gt;
+
+void test() {
+ // '1' is specified more then once
+ size_t addr[] = {0, 1, 1};
+ std::valarray&lt;size_t&gt;indirect(addr, 3);
+ std::valarray&lt;int&gt; 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 &lt;ios&gt;
using namespace std;
-template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
+template &lt;class T, class Traits = std::char_traits&lt;T&gt; &gt;
class my_stream1 : public std::basic_ios&lt;T, Traits&gt; {
};
-template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
+template &lt;class T, class Traits = std::char_traits&lt;T&gt; &gt;
class my_stream2 : public std::basic_ios&lt;T, Traits&gt; {
- class my_streambuf : public std::basic_streambuf&lt;T, Traits&gt; {
+ class my_streambuf
+ : public std::basic_streambuf&lt;T, Traits&gt; {
};
public:
my_stream2() {
@@ -995,28 +1277,35 @@ public:
};
void test() {
- my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;
- my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;
+ my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;;
+ my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;;
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 &lt;ios&gt;
using namespace std;
-template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
+template &lt;class T, class Traits = std::char_traits&lt;T&gt; &gt;
class my_stream1 : public std::basic_ios&lt;T, Traits&gt; {
};
-template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
+template &lt;class T, class Traits = std::char_traits&lt;T&gt; &gt;
class my_stream2 : public std::basic_ios&lt;T, Traits&gt; {
- class my_streambuf : public std::basic_streambuf&lt;T, Traits&gt; {
+ class my_streambuf
+ : public std::basic_streambuf&lt;T, Traits&gt; {
};
public:
my_stream2() {
@@ -1025,20 +1314,24 @@ public:
};
void test() {
- my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;
- my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;
+ my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;;
+ my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;;
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 &lt;fstream&gt;
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 &lt;fstream&gt;
void test() {
std::filebuf fb;
std::istream in(&amp;fb);
- std::ostream out(&amp;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-&gt;x; // warn
if (p1) {};
- S *p2 = f();
+ struct S *p2 = f();
int x2 = p2-&gt;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-&gt;b && p) {}; // warn
+ struct S *p = f();
+ if (p-&gt;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 &lt;vector&gt;
void test() {
std::vector&lt;int&gt; 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&lt;3; ++i); // warn
- for (int j=0; i&lt;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 &lt;math.h&gt;
-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 &amp; (|) operator. Did you mean
-&amp;&amp; (||) ?
-</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>&amp;</code>
+or <code>|</code> operator.
+Did you mean <code>&amp;&amp;</code> (<code>||</code>) ?</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
int f();
void test() {
bool b = true;
if (b &amp; 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 &gt; 5) // &lt;-
+
+<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 &gt; 5)
c += 1;
if (c &gt; 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 &amp;&amp; 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>&amp;&amp;</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&lt;7 &amp;&amp; a&lt;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 &amp;&amp; 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 &lt; -1) {}; // warn
- if (u &gt;= 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 &amp;&amp; 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 &lt;&lt;
-</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>&lt;&lt;</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 &lt;iostream&gt;
-void test() {
- int a;
+void test(int a) {
std::cout &lt;&lt; a ? "a" : "b"; // warn
- a &lt;&lt; a&gt;7 ? 1 : 2; // warn
}
-</pre></td><td class="aligned"></td></tr>
+</pre></div>
+<div class="example"><pre>
+void test(int a) {
+ a &lt;&lt; a &gt; 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 &lt;exception&gt;
+<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 &lt;exception&gt;
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 &lt;stdlib.h&gt;
+<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 &lt;limits.h&gt;
-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 &lt;limits.h&gt;
-<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; // &lt;-
+}
+</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 &lt;windows.h&gt;
void test() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
- BOOL fSuccess;
- fSuccess = CreateProcess(
- NULL, TEXT("MyProgram.exe"), NULL, NULL,
- TRUE, 0, NULL, NULL, &amp;si, &amp;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 &lt;windows.h&gt;
-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 &lt;windows.h&gt;
-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 &lt;vector&gt;
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 &lt;string.h&gt;
-void test() {
- const char* s = "abc";
+void test(const char* s) {
if (strlen(s) &gt; 0 &amp;&amp;
strlen(s) &lt; 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 &lt;string.h&gt;
-void test() {
- const char* s = "abc";
- if (strlen(s) &gt; 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 &lt;string&gt;
#include &lt;string.h&gt;
@@ -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 &lt;list&gt;
void test() {
std::list&lt;int&gt; l;
if (l.size() != 0) {}; // warn
}
-</pre></td><td class="aligned"></td></tr>
+</pre></div></div></td>
+<td class="aligned"></td></tr>
+
</table>