[cfe-commits] r165359 - in /cfe/trunk/www/analyzer: content.css potential_checkers.html
Ted Kremenek
kremenek at apple.com
Fri Oct 5 22:09:43 PDT 2012
Author: kremenek
Date: Sat Oct 6 00:09:43 2012
New Revision: 165359
URL: http://llvm.org/viewvc/llvm-project?rev=165359&view=rev
Log:
Add list of potential checkers. Provided by Anton Yartsev!
Added:
cfe/trunk/www/analyzer/potential_checkers.html
Modified:
cfe/trunk/www/analyzer/content.css
Modified: cfe/trunk/www/analyzer/content.css
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/content.css?rev=165359&r1=165358&r2=165359&view=diff
==============================================================================
--- cfe/trunk/www/analyzer/content.css (original)
+++ cfe/trunk/www/analyzer/content.css Sat Oct 6 00:09:43 2012
@@ -63,6 +63,38 @@
table.options td { padding:5px; padding-left:8px; padding-right:8px }
table.options td { text-align:left; font-size:9pt }
+table.checkers {
+ border: 1px #cccccc solid;
+ border-collapse: collapse;
+ margin:0px; margin-top:20px; margin-bottom:20px;
+ text-align:left;
+ table-layout: fixed;
+ width: 100%;
+ 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 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; }
+
/* 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}
#collapsetree,#collapsetree ul{list-style-type:none; width:auto; margin:0; padding:0}
Added: cfe/trunk/www/analyzer/potential_checkers.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/potential_checkers.html?rev=165359&view=auto
==============================================================================
--- cfe/trunk/www/analyzer/potential_checkers.html (added)
+++ cfe/trunk/www/analyzer/potential_checkers.html Sat Oct 6 00:09:43 2012
@@ -0,0 +1,1645 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>List of potential checkers</title>
+ <link type="text/css" rel="stylesheet" href="content.css">
+ <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>
+</head>
+<body>
+
+<div id="page">
+
+<!-- menu -->
+<!--#include virtual="menu.html.incl"-->
+<!-- page content -->
+<div id="content">
+<h1>List of potential checkers</h1>
+
+<!---------------------------- allocation/deallocation -------------------------->
+<h3>allocation/deallocation</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">memory.LeakNeverReleased<br>
+(C, C++)</span><br><br>
+Memory may be never released, potential leak of memory
+</td><td>
+<pre>
+#include <stdlib.h>
+
+int f() {};
+
+void test() {
+ int *p1 = (int*)malloc(sizeof(int)); // warn
+ int *p2 = new int; // warn
+ int x = f();
+ if (x==1)
+ return;
+ delete p2;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MismatchedFree
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Mismatched deallocation function is used
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+ int *p1 = new int;
+ int *p2 = new int[1];
+
+ free(p1); // warn
+ free(p2); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MismatchedDelete
+<br>(C, C++)</span><br><br>
+Mismatched deallocation function is used
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+ int *p1 = new int;
+ int *p2 = new int[1];
+ int *p3 = (int*)malloc(sizeof(int));
+
+ delete[] p1; // warn
+ delete p2; // warn
+ delete p3; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MultipleDelete
+<br>(C++)</span><br><br>
+Attempt to deallocate released memory
+</td><td><pre>
+#include <new>
+
+void test() {
+ int *p1 = new int;
+ int *p2 = new(p1) int;
+ int *p3 = p1;
+ delete p1;
+ delete p1; // warn
+ delete p2; // warn
+ delete p3; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.LeakPtrValChanged
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Potential memory leak: a pointer to newly allocated data loses its original
+value
+</td><td><pre>
+#include <stdlib.h>
+
+void f(const int *);
+void g(int *);
+
+void test() {
+ int *p1 = new int;
+ p1++; // warn
+ int *p2 = (int *)malloc(sizeof(int));
+ p2 = p1; // warn
+ int *p3 = new int;
+ f(p3);
+ p3++; // warn
+ int *p4 = new int;
+ f(p4);
+ p4++; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.DeallocateNonPtr
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Deallocation function is applied to non-pointer
+</td><td><pre>
+#include <stdlib.h>
+
+class A {
+ int *p;
+public:
+ operator int *() { return p; }
+};
+
+void test() {
+ A a;
+ delete a; // warn
+ free(a); // warn
+ const char *s = "text";
+ delete s; // warn
+ free(s); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.LeakEvalOrder<br>
+(C, C++)</span><br><br>
+Potential memory leak: argument evaluation order is undefined, g() may never be called
+</td><td><pre>
+#include <stdlib.h>
+
+void f1(int, int);
+void f2(int*, int*);
+int g(int *) { throw 1; };
+int h();
+
+void test() {
+ f1(g(new int), h()); // warn
+ f1(g((int *)malloc(sizeof(int))), h()); // warn
+ f2(new int, new int);
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.DstBufferTooSmall
+<br>(C, C++)</span><br><br>
+Destination buffer too small
+</td><td><pre>
+#include <string.h>
+
+void test() {
+ const char* s1 = "abc";
+ char *s2 = new char;
+ strcpy(s2, s1); // warn
+
+ int* p1 = new int[3];
+ int* p2 = new int;
+ memcpy(p2, p1, 3); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.NegativeArraySize
+<br>enhancement to experimental.security.MallocOverflow<br>(C, C++)
+</span><br><br>
+n is used to specify the buffer size may be negative
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+ int *p;
+ int n1 = -1;
+ p = new int[n1]; // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!-------------------------- constructors/destructors ------------------------->
+<h3>constructors/destructors</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">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();
+
+class A {
+ A() {}
+ ~A() { throw 1; } // warn
+};
+</pre></td><td></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; };
+
+class A {
+ A() {}
+ ~A() { f(); } // warn
+};
+</pre></td><td></td></tr>
+
+</table>
+
+<!--------------------------------- exceptions -------------------------------->
+<h3>exceptions</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">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></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() {
+ throw(1); // warn
+}
+</pre></td><td></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>
+struct S{};
+void f() throw(int) {
+ S s;
+ throw (s); // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!---------------------------- smart pointers --------------------------------->
+<h3>smart pointers</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">smartptr.AutoPtrInit<br>
+(C++03)</span><br><br>
+auto_ptr should store a pointer to an object obtained via new as allocated
+memory will be cleaned using delete
+</td><td><pre>
+#include <stdlib.h>
+#include <memory>
+
+void test() {
+ std::auto_ptr<int> p1(new int); // Ok
+ std::auto_ptr<int> p2(new int[3]); // warn
+ std::auto_ptr<int>
+ p3((int *)malloc(sizeof(int))); // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!---------------------------- undefined behavior ----------------------------->
+<h3>undefined behavior</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">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>
+#include <cstdlib>
+
+class A {
+public:
+ ~A() {
+ std::exit(1); // warn
+ }
+};
+
+A a;
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.LocalStaticDestroyed
+<br>(C++)</span><br><br>
+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>
+void f();
+
+class A {
+public:
+ ~A() {
+ f(); // warn
+ }
+};
+
+class B {};
+
+A a;
+
+void f() {
+ static B b; // <-
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.UseAfterRelease
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Pointer to deleted object is referenced (The effect of using an invalid pointer
+value is undefined)
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+ int *p = new int;
+ delete p;
+ int i = *p; // warn
+}
+
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ZeroAllocDereference
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+The effect of dereferencing a pointer returned as a request for zero size is
+undefined
+</td><td><pre>
+#include <stdlib.h>
+
+int *p = new int[0];
+int i = p[0]; // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.DeadReferenced
+<br>(C++)</span><br><br>
+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
+#include <new>
+
+class A {
+public:
+ int i;
+ void f() {};
+};
+
+class B : public A {
+};
+
+void test() {
+ B *b = new B;
+ new(b) A;
+ b->i; // warn
+ b->f(); // warn
+ static_cast<A*>(b); // warn
+ dynamic_cast<A*>(b); // warn
+ delete b; // warn
+}
+
+// C++11
+#include <new>
+
+class A {
+public:
+ int i;
+ void f() {};
+};
+
+class B : public A {
+public:
+ ~B() {};
+};
+
+void test() {
+ A *a = new A;
+ new(a) B;
+ a->i; // warn
+ a->f(); // warn
+ B *b = new B;
+ new(b) A;
+ b->i; // warn
+ b->f(); // warn
+ static_cast<A*>(b); // warn
+ dynamic_cast<A*>(b); // warn
+ delete b; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ObjLocChanges
+<br>(C++)</span><br><br>
+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>
+#include <new>
+
+class T { };
+struct B {
+ ~B();
+};
+
+void test() {
+ B *b1 = new B;
+ B b2;
+ new (b1) T;
+ new (&b2) T;
+ delete b1; // warn
+} // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ExprEvalOrderUndef
+<br>(C, C++03)</span><br><br>
+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 () {
+ int i = 0;
+ int v[1] = {0};
+ i = v[i++]; // warn
+ i = ++i + 1; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.StaticInitReentered
+<br>(C)</span><br><br>
+Undefined behavior: static declaration is re-entered while the object is being
+initialized
+</td><td><pre>
+int test(int i) {
+ static int s = test(2*i); // warn
+ return i+1;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ConstModified
+<br>(C, C++)</span><br><br>
+Undefined behavior: const object is being modified
+</td><td><pre>
+#include <stdlib.h>
+
+class X {
+public :
+ mutable int i;
+ int j;
+};
+class Y {
+public :
+ X x;
+ Y();
+};
+
+void test() {
+ const int *ciq =
+ (int *)malloc(sizeof(int));
+ int *iq = const_cast<int *>(ciq);
+ *iq = 1; // warn
+
+ const Y y;
+ Y* p = const_cast<Y*>(&y);
+ p->x.i = 1; // ok
+ p->x.j = 1; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.DeadDestructed
+<br>(C++)</span><br><br>
+Undefined behavior: the destructor is invoked for an object whose lifetime
+has ended
+</td><td><pre>
+class A {
+public:
+ void f() {};
+ A() {};
+ ~A() {};
+};
+
+void test() {
+ A a;
+ a.~A();
+} // warn
+</pre></td><td></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>
+class A {
+public :
+ A(int );
+};
+class B : public A {
+public :
+ int f();
+ B() : A(f()) {} // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberOrBaseRefBeforeCtor
+<br>(C++)</span><br><br>
+C++ Undefined behavior: non-static member or base class of non-POD class type
+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
+struct POD {
+ int i;
+};
+
+struct non_POD : public POD {
+ int j;
+ POD pod;
+};
+
+extern POD pod;
+extern non_POD non_pod;
+
+int *p1 = &non_pod.j; // warn
+int *p2 = &non_pod.pod.i; // warn
+int *p3 = &pod.i; // ok
+POD *p4 = & non_pod; // warn
+
+POD a;
+non_POD b;
+
+struct S {
+ int *k;
+ non_POD non_pod;
+ S() : k(&non_pod.j) {} // warn
+};
+
+// C++11
+struct trivial {
+ int i;
+};
+
+struct non_trivial: public trivial {
+ non_trivial() {};
+ int j;
+ trivial pod;
+};
+
+extern trivial t;
+extern non_trivial nt;
+
+int *p1 = &nt.j; // warn
+int *p2 = &nt.i; // warn
+int *p3 = &t.i; // ok
+trivial *p4 = &nt;
+
+trivial t;
+non_trivial nt;
+
+struct S {
+ int *k;
+ non_trivial nt;
+ S() : k(&nt.j) {} // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberRefAfterDtor
+<br>(C++)</span><br><br>
+C++03: Undefined behavior: non-static member of non-POD class type is referred
+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() {};
+};
+
+void test() {
+ non_POD *non_pod = new non_POD();
+ non_pod->~non_POD();
+ non_pod->f(); // warn
+}
+
+// C++11
+struct S {
+ ~S() {};
+ void f() {};
+};
+
+void test() {
+ S *s = new S();
+ s->~S();
+ s->f(); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.CtorForeignCall
+<br>(C++)</span><br><br>
+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>
+class A {
+public:
+ virtual void f() {};
+};
+
+class B {
+public:
+ B(A* a) { a->f(); } // warn
+};
+
+class C : public A, B {
+public:
+ C() : B((A*)this) {}
+};
+</pre></td><td></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
+construction whose type is neither the constructors own class or one of its
+bases
+</td><td><pre>
+#include <typeinfo>
+
+class A {
+public:
+ virtual void f() {};
+};
+
+class B {
+public:
+ B(A* a) {
+ typeid(*a); // warn
+ dynamic_cast<B*>(a); //warn
+ }
+};
+
+class C : public A, B {
+public:
+ C() : B((A*)this) {}
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberRefInCatch
+undefbehavior.BaseRefInCatch
+<br>(C++)</span><br><br>
+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>
+class C {
+ int i;
+public :
+ C()
+ try
+ : i(1) {}
+ catch (...)
+ {
+ i=2; // warn
+ }
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ReturnAtCatchEnd
+<br>(C++)</span><br><br>
+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>
+int test() try {
+}
+catch(int) {
+} // warn
+</pre></td><td></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>
+#include <memory>
+
+void test() {
+ int *data = new int;
+ std::auto_ptr<int> p(data);
+ std::auto_ptr<int> q(data); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.BasicStringBoundAccess
+<br>(C++03)</span><br><br>
+Undefined behavior: out-of-bound basic_string access
+</td><td><pre>
+void test() {
+ std::basic_string<char> s;
+ char c = s[10]; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.BasicStringBoundModification
+<br>(C++)</span><br><br>
+Undefined behavior: out-of-bound basic_string modification
+</td><td><pre>
+void test() {
+ std::basic_string<char> s;
+ s[10] = 0; // warn
+}
+</pre></td><td></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>
+#include <vector>
+
+void test() {
+ std::vector<int> v;
+ int i = *v.end(); // warn
+ *v.end() = 0; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.QsortNonPOD
+undefbehavior.QsortNonTrivial
+<br>C++</span><br><br>
+C++03: Undefined behavior: the objects in the array passed to qsort are of
+non-POD type<br>
+C++11: Undefined behavior: the objects in the array passed to qsort are of
+non-trivial type
+</td><td><pre>
+// C++03
+#include <cstdlib>
+
+struct non_POD {
+ int i;
+ non_POD(int ii) : i(ii) {}
+};
+
+non_POD values[] = { non_POD(2), non_POD(1) };
+
+int compare(const void *a,
+ const void *b) {
+ return ( (*(non_POD*)a).i -
+ (*(non_POD*)b).i );
+}
+
+void test() {
+ qsort(values, 2, sizeof(non_POD),
+ compare); // warn
+}
+
+// C++11
+#include <cstdlib>
+
+struct S {};
+
+struct trivial_non_POD : public S {
+ int i;
+};
+
+struct non_trivial {
+ int i;
+ 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 compare2(const void *a,
+ const void *b) {
+ return ( (*(non_trivial *)a).i -
+ (*(non_trivial *)b).i );
+}
+
+void test() {
+ qsort(tnp, 2, sizeof(trivial_non_POD),
+ compare1); // ok
+ qsort(nt, 2, sizeof(non_trivial),
+ compare2); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ThrowWhileCopy
+<br>C++</span><br><br>
+Undefined behavior: copy constructor/assignment operator can throw an exception.
+The effects are undefined if an exception is thrown.
+</td><td><pre>
+struct S {
+ int i, j;
+ S (const S &s) {
+ i = s.i;
+ throw 1; // warn
+ j = s.j;
+ };
+ S& operator=(const S &s) {
+ i = s.i;
+ throw 1; // warn
+ j = s.j;
+ }
+};
+</pre></td><td></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>
+#include <valarray>
+
+struct S {
+ int i;
+ S(int ii) : i(ii) {};
+};
+
+void test(void) {
+ S s[] = { S(1), S(2) };
+ std::valarray<S> v(s,3); // warn
+}
+</pre></td><td></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>
+// C++03
+#include <valarray>
+
+void test(void) {
+ std::valarray<int> a(0, 1), b(0, 2);
+ std::valarray<bool> c(false, 1);
+ a = b; // warn
+ a *= b; // warn
+ a = a * b; // warn
+ c = a == b; // warn
+ b.resize(1);
+ a = b; // OK
+}
+
+// C++11
+#include <valarray>
+
+void test(void) {
+ std::valarray<int> a(0, 1), b(0, 2);
+ std::valarray<bool> c(false, 1);
+ a = b; // ok
+ a *= b; // ok
+ a = a * b; // warn
+ c = a == b; // warn
+ b.resize(1);
+ a = b; // OK
+}
+</pre></td><td></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>
+#include <valarray>
+
+void test(void) {
+ std::valarray<int> v(0, 0);
+ v.sum(); // warn
+ v.min(); // warn
+ v.max(); // warn
+}
+</pre></td><td></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>
+#include <valarray>
+
+void test() {
+ size_t addr[] = {0, 1, 1}; // N is 1
+ std::valarray<size_t>indirect(addr, 3);
+ std::valarray<int> a(0, 5), b(1, 3);
+ a[indirect] = b; //warn
+ a[indirect] *= b; //warn
+}
+</pre></td><td></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>
+#include <ios>
+
+using namespace std;
+template <class T, class Traits = std::char_traits<T>>
+class my_stream1 : public std::basic_ios<T, Traits> {
+};
+
+template <class T, class Traits = std::char_traits<T>>
+class my_stream2 : public std::basic_ios<T, Traits> {
+ class my_streambuf : public std::basic_streambuf<T, Traits> {
+ };
+public:
+ my_stream2() {
+ this->init(new my_streambuf);
+ }
+};
+
+void test() {
+ my_stream1<char> *p1 = new my_stream1<char>
+ my_stream2<char> *p2 = new my_stream2<char>
+ delete p1; // warn
+ delete p2; // ok
+}
+</pre></td><td></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>
+#include <ios>
+
+using namespace std;
+template <class T, class Traits = std::char_traits<T>>
+class my_stream1 : public std::basic_ios<T, Traits> {
+};
+
+template <class T, class Traits = std::char_traits<T>>
+class my_stream2 : public std::basic_ios<T, Traits> {
+ class my_streambuf : public std::basic_streambuf<T, Traits> {
+ };
+public:
+ my_stream2() {
+ this->init(new my_streambuf);
+ }
+};
+
+void test() {
+ my_stream1<char> *p1 = new my_stream1<char>
+ my_stream2<char> *p2 = new my_stream2<char>
+ p1->narrow('a', 'b'); // warn
+ p2->narrow('a', 'b'); // ok
+ delete p1; // warn
+ delete p2; // ok
+}
+</pre></td><td></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>
+#include <fstream>
+
+class my_streambuf : public std::streambuf {
+ void f() {
+ seekpos(-1); // warn
+ }
+};
+
+void test() {
+ std::filebuf fb;
+ std::istream in(&fb);
+ std::ostream out(&fb);
+ std::filebuf::off_type pos(-1);
+ in.seekg(pos); // warn
+ out.seekp(-1); // warn
+}
+</pre></td><td></td></tr>
+</table>
+
+<!------------------------------- different ----------------------------------->
+<h3>different</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">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></td></tr>
+
+<tr><td><span class="name">different.IdenticalExprBinOp
+<br>(C)</span><br><br>
+There are identical sub-expressions to the left and to the right of the
+operator
+</td><td><pre>
+#define A 1
+#define B 1
+
+bool isNan(double d) {
+ return d != d; // ok
+}
+
+int f();
+
+void test() {
+ int i = 0;
+ if (i != 0 && i != 0) {} // warn
+
+ if(i == A || i == B) {} // ok
+
+ if (++i != 0 && ++i != 0) {} // ok
+
+ if (f() && f()) {} // ok
+}
+</pre></td><td></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></td></tr>
+
+<tr><td><span class="name">different.IdenticalCondIfElseIf
+<br>(C)</span><br><br>
+The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a
+probability of logical error presence
+</td><td><pre>
+void test() {
+ int i = 7;
+ if (i == 1) {}
+ else if (i == 1) {} // warn
+}
+</pre></td><td></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;
+ i=1;
+ i=2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.NullDerefStmtOrder
+<br>enhancement to core.NullDereference<br>(C)</span><br><br>
+Dereferencing of the null pointer might take place. Checking the pointer for
+null should be performed first
+</td><td><pre>
+struct S {
+ int x;
+};
+
+S* f();
+
+void test() {
+ S *p1 = f();
+ int x1 = p1->x; // warn
+ if (p1) {};
+
+ S *p2 = f();
+ int x2 = p2->x; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.NullDerefCondOrder
+<br>enhancement to core.NullDereference<br>(C)</span><br><br>
+Dereferencing of the null pointer might take place. Checking the pointer for
+null should be performed first
+</td><td><pre>
+struct S{bool b;};
+
+S* f();
+
+void test() {
+ S *p = f();
+ if (p->b && p) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalStmtThenElse
+<br>(C)</span><br><br>
+The 'else' statement is equivalent to the 'then' statement
+</td><td><pre>
+void test() {
+ int i;
+ if (i==1) {
+ i++;
+ }
+ else { // warn
+ i++;
+ }
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.MultipleAccessors
+<br>(C++)</span><br><br>
+multiple accessors met for 'class::field'
+</td><td><pre>
+class A {
+ int i;
+ int j;
+public:
+ int getI() { return i; }
+ int getJ() { return i; } // warn
+ void setI(int& ii) { i = ii; }
+ void setJ(int& jj) { i = jj; } // warn
+};
+</pre></td><td></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>
+class A {
+public:
+ int i; // warn
+ int getI() { return i; }
+ void setI(int& ii) { i = ii; }
+};
+</pre></td><td></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>
+#include <vector>
+
+void test() {
+ std::vector<int> v;
+ v.empty(); // warn
+}
+</pre></td><td></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>
+void test() {
+ int i;
+ int j;
+ for (j=0; j<3; ++i); // warn
+ for (int j=0; i<3; ++j); // warn
+}
+</pre></td><td></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>
+#include <math.h>
+
+void test() {
+ double b = sin(M_PI / 6.0);
+ if (b == 0.5) // warn
+ b = 0;
+}
+</pre></td><td></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></td></tr>
+
+<tr><td><span class="name">different.BitwiseOpBoolArg
+<br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
+bool value is used at the left/right part of the & (|) operator. Did you mean
+&& (||) ?
+</td><td><pre>
+int f();
+
+void test() {
+ bool b = true;
+ if (b & f()) {} // warn
+}
+</pre></td><td></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;
+ switch(c){
+ case 1:
+ c += 1; break;
+ defalt: // warn
+ c -= 1; break;
+ }
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalCondIfIf
+<br>(C)</span><br><br>
+The conditions of two subsequent if statements are identical
+</td><td><pre>
+void test() {
+ int c = 7;
+ if (c > 5) // <-
+ c += 1;
+ if (c > 5) // warn
+ c -= 1;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.CondOpIdenticalReturn
+<br>(C)</span><br><br>
+The return expressions of the ?: operator are identical
+</td><td><pre>
+void test() {
+ unsigned a;
+ a = a > 5 ? a : a; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.UnaryPlusWithUnsigned
+<br>(C)</span><br><br>
+Using unary + with unsigned is meaningless
+</td><td><pre>
+void test() {
+ unsigned a;
+ a = +a; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.LogicalOpUselessArg
+<br>(C)</span><br><br>
+The second operand of the && operator has no impact on expression result
+</td><td><pre>
+void test() {
+ unsigned a;
+ if (a<7 && a<10) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.SameResLogicalExpr
+<br>(C)</span><br><br>
+The expression always evaluates to true/false
+</td><td><pre>
+void test() {
+ int i=0;
+ if (i!=0) {}; // warn
+ if (i==0 && i==1) {}; // warn
+ if (i<0 || i>=0) {}; // warn
+}
+</pre></td><td></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>
+void test() {
+ unsigned u;
+ if (u < -1) {}; // warn
+ if (u >= 0) {}; // warn
+}
+</pre></td><td></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 f();
+
+void test() {
+ bool b;
+ int x, y;
+ if((b = x != y)) {} // ok
+ if((x = f() != y)) {} // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.OpPrecedenceIifShift
+<br>(C)</span><br><br>
+?: has lower precedence then <<
+</td><td><pre>
+#include <iostream>
+
+void test() {
+ int a;
+ std::cout << a ? "a" : "b"; // warn
+ a << a>7 ? 1 : 2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.ObjectUnused
+<br>(C++)</span><br><br>
+The object was created but is not being used<br><br>
+The exception object was created but is not being used. Did you mean
+throw std::exception(); ?
+</td><td><pre>
+#include <exception>
+
+struct S {
+ int x, y;
+ S(int xx, int yy) : x(xx), y(yy) {
+ }
+ S(int xx) {
+ S(xx, 0); // warn
+ }
+};
+
+void test() {
+ S(0, 0); // warn
+ std::exception(); // warn
+}
+</pre></td><td></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
+}
+</pre></td><td></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>
+bool test() {
+ return 1.; // warn
+ return ""; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.ArrayBound
+<br>enhancement to experimental.security.ArrayBound[v2]<br>(C, C++)</span><br><br>
+Out-of-bound dynamic array access
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+ int *p2 = new int[1];
+ if(p2[1]) {}; // warn
+ int i = 1;
+ if(p2[i]) {}; // warn
+}
+</pre></td><td></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>
+void test(char* string) {
+ char buf[24];
+ strcpy(buf, string); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IntegerOverflow
+<br>(C)</span><br><br>
+Integer overflow
+</td><td><pre>
+#include <limits.h>
+
+int f(int x) {
+ return INT_MAX+1; // warn
+}
+
+void test() {
+ int x = INT_MAX+1; // warn
+ f(INT_MAX+1); // warn
+
+ int y = INT_MAX/2+1; // warn
+ x = y*2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.SignExtension
+<br>(C)</span><br><br>
+Unexpected sign extension might take place
+</td><td><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
+ f(si); // warn
+ ui = g(); // warn
+ return si; // warn
+}
+</pre></td><td></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;
+ 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
+ f(sll); // warn
+ ss = g(); // warn
+ return sll; // warn
+}
+</pre></td><td></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; // <-
+public:
+ C() { p = new int; }
+ ~C() { delete p; }
+};
+</pre></td><td></td></tr>
+
+</table>
+
+<!------------------------------- WinAPI -------------------------------------->
+<h3>WinAPI</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">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>
+#include <windows.h>
+
+void test() {
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ BOOL fSuccess;
+ fSuccess = CreateProcess(
+ NULL, TEXT("MyProgram.exe"), NULL, NULL,
+ TRUE, 0, NULL, NULL, &si, &pi);
+} // warn
+</pre></td><td></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>
+#include <windows.h>
+
+void test() {
+ HINSTANCE h = LoadLibrary("X.dll"); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">WinAPI.WideCharToMultiByte
+<br>(C)</span><br><br>
+Buffer overrun while calling WideCharToMultiByte
+</td><td><pre>
+#include <windows.h>
+
+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></td></tr>
+
+</table>
+
+<!------------------------------ optimization --------------------------------->
+<h3>optimization</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">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></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>
+#include <vector>
+
+void test() {
+ std::vector<int> v;
+ std::vector<int>::const_iterator it;
+ for(it = v.begin();
+ it != v.end(); it++) {}; // warn
+}
+</pre></td><td></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>
+#include <string.h>
+
+void test() {
+ const char* s = "abc";
+ if (strlen(s) > 0 &&
+ strlen(s) < 7) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.EmptyCstrDetect
+<br>(C)</span><br><br>
+Optimization: it is more efficient to use str[0] != \0 to identify an empty
+string
+</td><td><pre>
+#include <string.h>
+
+void test() {
+ const char* s = "abc";
+ if (strlen(s) > 0) {}; // warn
+}
+</pre></td><td></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>
+#include <string>
+#include <string.h>
+
+void test() {
+ std::string s;
+ if (strlen(s.c_str()) != 0) {}; // warn
+}
+</pre></td><td></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>
+#include <list>
+
+void test() {
+ std::list<int> l;
+ if (l.size() != 0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<br>
+</div> <!-- page -->
+</div> <!-- content -->
+</body>
+</html>
More information about the cfe-commits
mailing list