[analyzer] Alpha and implicit checker lists, expand/collapse feature.

The list of alpha and the list of implicit checkers added. An ability to expand/collapse long texts added. Markup fixed.

http://reviews.llvm.org/D3457

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209131 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Yartsev 2014-05-19 15:04:55 +00:00
parent 323f398054
commit 76790c5cf0
11 changed files with 1310 additions and 129 deletions

View File

@ -0,0 +1,848 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Alpha Checks</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 onload="initExpandCollapse()">
<div id="page">
<!--#include virtual="menu.html.incl"-->
<div id="content">
<h1>Alpha Checkers</h1>
Experimental checkers in addition to the <a href = "available_checks.html">
Default Checkers</a>. These are checkers with known issues or limitations that
keep them from being on by default. They are likely to have false positives.
Bug reports are welcome but will likely not be investigated for some time.
Patches welcome!
<ul>
<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li>
<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li>
<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li>
<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li>
<li><a href="#security_alpha_checkers">Security Alpha Checkers</a></li>
<li><a href="#unix_alpha_checkers">Unix Alpha Checkers</a></li>
</ul>
<!------------------------------ core alpha ----------------------------------->
<h3 id="core_alpha_checkers">Core Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.BoolAssignment</span><span class="lang">
(ObjC)</span><div class="descr">
Warn about assigning non-{0,1} values to boolean variables.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
BOOL b = -1; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.CastSize</span><span class="lang">
(C)</span><div class="descr">
Check when casting a malloc'ed type T, whether the size is a multiple of the
size of T (Works only with <span class="name">unix.Malloc</span>
or <span class="name">alpha.unix.MallocWithAnnotations</span>
checks enabled).</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int *x = (int *)malloc(11); // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.CastToStruct</span><span class="lang">
(C, C++)</span><div class="descr">
Check for cast from non-struct pointer to struct pointer.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
struct s {};
void test(int *p) {
struct s *ps = (struct s *) p; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// C++
class c {};
void test(int *p) {
c *pc = (c *) p; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.FixedAddr</span><span class="lang">
(C)</span><div class="descr">
Check for assignment of a fixed address to a pointer.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int *p;
p = (int *) 0x10000; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.IdenticalExpr</span><span class="lang">
(C, C++)</span><div class="descr">
Warn about suspicious uses of identical expressions.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
void test() {
int a = 5;
int b = a | 4 | a; // warn: identical expr on both sides
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// C++
bool f(void);
void test(bool b) {
int i = 10;
if (f()) { // warn: true and false branches are identical
do {
i--;
} while (f());
} else {
do {
i--;
} while (f());
}
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.PointerArithm</span><span class="lang">
(C)</span><div class="descr">
Check for pointer arithmetic on locations other than array
elements.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int x;
int *p;
p = &amp;x + 1; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.PointerSub</span><span class="lang">
(C)</span><div class="descr">
Check for pointer subtractions on two pointers pointing to different memory
chunks.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int x, y;
int d = &amp;y - &amp;x; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.core.SizeofPtr</span><span class="lang">
(C)</span><div class="descr">
Warn about unintended use of <code>sizeof()</code> on pointer
expressions.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
struct s {};
int test(struct s *p) {
return sizeof(p);
// warn: sizeof(ptr) can produce an unexpected result
}
</pre></div></div></td></tr>
</tbody></table>
<!--------------------------- cplusplus alpha --------------------------------->
<h3 id="cplusplus_alpha_checkers">C++ Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.cplusplus.NewDeleteLeaks</span><span class="lang">
(C++)</span><div class="descr">
Check for memory leaks. Traces memory managed by <code>new</code>/<code>
delete</code>.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int *p = new int;
} // warn
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.cplusplus.VirtualCall</span><span class="lang">
(C++)</span><div class="descr">
Check virtual member function calls during construction or
destruction.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
class A {
public:
A() {
f(); // warn
}
virtual void f();
};
</pre></div><div class="separator"></div>
<div class="example"><pre>
class A {
public:
~A() {
this-&gt;f(); // warn
}
virtual void f();
};
</pre></div></div></td></tr>
</tbody></table>
<!--------------------------- dead code alpha --------------------------------->
<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.deadcode.UnreachableCode</span><span class="lang">
(C, C++, ObjC)</span><div class="descr">
Check unreachable code.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
int test() {
int x = 1;
while(x);
return x; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// C++
void test() {
int a = 2;
while (a > 1)
a--;
if (a > 1)
a++; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// Objective-C
void test(id x) {
return;
[x retain]; // warn
}
</pre></div></div></td></tr>
</tbody></table>
<!---------------------------- OS X alpha -------------------------------------->
<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.Dealloc</span><span class="lang">
(ObjC)</span><div class="descr">
Warn about Objective-C classes that lack a correct implementation
of <code>-dealloc</code>.
</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyObject : NSObject {
id _myproperty;
}
@end
@implementation MyObject // warn: lacks 'dealloc'
@end
</pre></div><div class="separator"></div>
<div class="example"><pre>
@interface MyObject : NSObject {}
@property(assign) id myproperty;
@end
@implementation MyObject // warn: does not send 'dealloc' to super
- (void)dealloc {
self.myproperty = 0;
}
@end
</pre></div><div class="separator"></div>
<div class="example"><pre>
@interface MyObject : NSObject {
id _myproperty;
}
@property(retain) id myproperty;
@end
@implementation MyObject
@synthesize myproperty = _myproperty;
// warn: var was retained but wasn't released
- (void)dealloc {
[super dealloc];
}
@end
</pre></div><div class="separator"></div>
<div class="example"><pre>
@interface MyObject : NSObject {
id _myproperty;
}
@property(assign) id myproperty;
@end
@implementation MyObject
@synthesize myproperty = _myproperty;
// warn: var wasn't retained but was released
- (void)dealloc {
[_myproperty release];
[super dealloc];
}
@end
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.DirectIvarAssignment</span><span class="lang">
(ObjC)</span><div class="descr">
Check that Objective C properties follow the following rule: the property
should be set with the setter, not though a direct assignment.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass : NSObject {}
@property (readonly) id A;
- (void) foo;
@end
@implementation MyClass
- (void) foo {
_A = 0; // warn
}
@end
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions</span><span class="lang">
(ObjC)</span><div class="descr">
Check for direct assignments to instance variables in the methods annotated
with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@interface MyClass : NSObject {}
@property (readonly) id A;
- (void) fAnnotated __attribute__((
annotate("objc_no_direct_instance_variable_assignment")));
- (void) fNotAnnotated;
@end
@implementation MyClass
- (void) fAnnotated {
_A = 0; // warn
}
- (void) fNotAnnotated {
_A = 0; // no warn
}
@end
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.InstanceVariableInvalidation</span><span class="lang">
(ObjC)</span><div class="descr">
Check that the invalidatable instance variables are invalidated in the methods
annotated with <code>objc_instance_variable_invalidator</code>.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@protocol Invalidation &lt;NSObject&gt;
- (void) invalidate
__attribute__((annotate("objc_instance_variable_invalidator")));
@end
@interface InvalidationImpObj : NSObject &lt;Invalidation&gt;
@end
@interface SubclassInvalidationImpObj : InvalidationImpObj {
InvalidationImpObj *var;
}
- (void)invalidate;
@end
@implementation SubclassInvalidationImpObj
- (void) invalidate {}
@end
// warn: var needs to be invalidated or set to nil
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.osx.cocoa.MissingInvalidationMethod</span><span class="lang">
(ObjC)</span><div class="descr">
Check that the invalidation methods are present in classes that contain
invalidatable instance variables.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
@protocol Invalidation &lt;NSObject&gt;
- (void)invalidate
__attribute__((annotate("objc_instance_variable_invalidator")));
@end
@interface NeedInvalidation : NSObject &lt;Invalidation&gt;
@end
@interface MissingInvalidationMethodDecl : NSObject {
NeedInvalidation *Var; // warn
}
@end
@implementation MissingInvalidationMethodDecl
@end
</pre></div></div></td></tr>
</tbody></table>
<!------------------------- security alpha ------------------------------------>
<h3 id="security_alpha_checkers">Security Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.security.ArrayBound</span><span class="lang">
(C)</span><div class="descr">
Warn about buffer overflows (older checker).</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
char *s = "";
char c = s[1]; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
struct seven_words {
int c[7];
};
void test() {
struct seven_words a, *p;
p = &a;
p[0] = a;
p[1] = a;
p[2] = a; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// note: requires unix.Malloc or
// alpha.unix.MallocWithAnnotations checks enabled.
void test() {
int *p = malloc(12);
p[3] = 4; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
char a[2];
int *b = (int*)a;
b[1] = 3; // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.security.ArrayBoundV2</span><span class="lang">
(C)</span><div class="descr">
Warn about buffer overflows (newer checker).</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
char *s = "";
char c = s[1]; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
int buf[100];
int *p = buf;
p = p + 99;
p[1] = 1; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// note: compiler has internal check for this.
// Use -Wno-array-bounds to suppress compiler warning.
void test() {
int buf[100][100];
buf[0][-1] = 1; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// note: requires alpha.security.taint check turned on.
void test() {
char s[] = "abc";
int x = getchar();
char c = s[x]; // warn: index is tainted
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.security.MallocOverflow</span><span class="lang">
(C)</span><div class="descr">
Check for overflows in the arguments to <code>malloc()</code>.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(int n) {
void *p = malloc(n * sizeof(int)); // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.security.ReturnPtrRange</span><span class="lang">
(C)</span><div class="descr">
Check for an out-of-bound pointer being returned to callers.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
static int A[10];
int *test() {
int *p = A + 10;
return p; // warn
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
int test(void) {
int x;
return x; // warn: undefined or garbage returned
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.security.taint.TaintPropagation</span><span class="lang">
(C)</span><div class="descr">
Generate taint information used by other checkers.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
char x = getchar(); // 'x' marked as tainted
system(&x); // warn: untrusted data is passed to a system call
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// note: compiler internally checks if the second param to
// sprintf is a string literal or not.
// Use -Wno-format-security to suppress compiler warning.
void test() {
char s[10], buf[10];
fscanf(stdin, "%s", s); // 's' marked as tainted
sprintf(buf, s); // warn: untrusted data as a format string
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
size_t ts;
scanf("%zd", &ts); // 'ts' marked as tainted
int *p = (int *)malloc(ts * sizeof(int));
// warn: untrusted data as bufer size
}
</pre></div></div></td></tr>
</tbody></table>
<!--------------------------- unix alpha -------------------------------------->
<h3 id="unix_alpha_checkers">Unix Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.Chroot</span><span class="lang">
(C)</span><div class="descr">
Check improper use of <code>chroot</code>.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void f();
void test() {
chroot("/usr/local");
f(); // warn: no call of chdir("/") immediately after chroot
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.MallocWithAnnotations</span><span class="lang">
(C)</span><div class="descr">
Check for memory leaks, double free, and use-after-free problems. Assumes that
all user-defined functions which might free a pointer are
annotated.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
void test() {
int *p = my_malloc(1);
} // warn: potential leak
</pre></div><div class="separator"></div>
<div class="example"><pre>
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
void test() {
int *p = my_malloc(1);
my_free(p);
my_free(p); // warn: attempt to free released
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
void test() {
int *p = my_malloc(1);
my_hold(p);
free(p); // warn: attempt to free non-owned memory
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
void test() {
int *p = malloc(1);
my_free(p);
*p = 1; // warn: use after free
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.PthreadLock</span><span class="lang">
(C)</span><div class="descr">
Simple lock -> unlock checker; applies to:<div class=functions>
pthread_mutex_lock<br>
pthread_rwlock_rdlock<br>
pthread_rwlock_wrlock<br>
lck_mtx_lock<br>
lck_rw_lock_exclusive<br>
lck_rw_lock_shared<br>
pthread_mutex_trylock<br>
pthread_rwlock_tryrdlock<br>
pthread_rwlock_tryrwlock<br>
lck_mtx_try_lock<br>
lck_rw_try_lock_exclusive<br>
lck_rw_try_lock_shared<br>
pthread_mutex_unlock<br>
pthread_rwlock_unlock<br>
lck_mtx_unlock<br>
lck_rw_done</div></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
pthread_mutex_t mtx;
void test() {
pthread_mutex_lock(&mtx);
pthread_mutex_lock(&mtx);
// warn: this lock has already been acquired
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
lck_mtx_t lck1, lck2;
void test() {
lck_mtx_lock(&lck1);
lck_mtx_lock(&lck2);
lck_mtx_unlock(&lck1);
// warn: this was not the most recently acquired lock
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
lck_mtx_t lck1, lck2;
void test() {
if (lck_mtx_try_lock(&lck1) == 0)
return;
lck_mtx_lock(&lck2);
lck_mtx_unlock(&lck1);
// warn: this was not the most recently acquired lock
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.SimpleStream</span><span class="lang">
(C)</span><div class="descr">
Check for misuses of stream APIs:<div class=functions>
fopen<br>
fclose</div>(demo checker, the subject of the demo
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
,<a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">Video</a>)
by Anna Zaks and Jordan Rose presented at the <a href="http://llvm.org/devmtg/2012-11/">
2012 LLVM Developers' Meeting).</a></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
FILE *F = fopen("myfile.txt", "w");
} // warn: opened file is never closed
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *F = fopen("myfile.txt", "w");
if (F)
fclose(F);
fclose(F); // warn: closing a previously closed file stream
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.Stream</span><span class="lang">
(C)</span><div class="descr">
Check stream handling functions:<div class=functions>fopen<br>
tmpfile<br>
fclose<br>
fread<br>
fwrite<br>
fseek<br>
ftell<br>
rewind<br>
fgetpos<br>
fsetpos<br>
clearerr<br>
feof<br>
ferror<br>
fileno</div></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
FILE *p = fopen("foo", "r");
} // warn: opened file is never closed
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *p = fopen("foo", "r");
fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
fclose(p);
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *p = fopen("foo", "r");
if (p)
fseek(p, 1, 3);
// warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
fclose(p);
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *p = fopen("foo", "r");
fclose(p);
fclose(p); // warn: already closed
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
void test() {
FILE *p = tmpfile();
ftell(p); // warn: stream pointer might be NULL
fclose(p);
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.BufferOverlap</span><span class="lang">
(C)</span><div class="descr">
Checks for overlap in two buffer arguments; applies to:<div class=functions>
memcpy<br>
mempcpy</div></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int a[4] = {0};
memcpy(a + 2, a + 1, 8); // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.NotNullTerminated</span><span class="lang">
(C)</span><div class="descr">
Check for arguments which are not null-terminated strings; applies
to:<div class=functions>
strlen<br>
strnlen<br>
strcpy<br>
strncpy<br>
strcat<br>
strncat</div></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
int y = strlen((char *)&test); // warn
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
alpha.unix.cstring.OutOfBounds</span><span class="lang">
(C)</span><div class="descr">
Check for out-of-bounds access in string functions; applies
to:<div class=functions>
strncopy<br>
strncat</div></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(char *y) {
char x[4];
if (strlen(y) == 4)
strncpy(x, y, 5); // warn
}
</pre></div></div></td></tr>
</tbody></table>
</div> <!-- page -->
</div> <!-- content -->
</body>
</html>

View File

@ -47,15 +47,9 @@ Experimental (Alpha) Checkers</a>.
<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>
<thead><tr><td>Name, Description</td><td>Example</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">
@ -370,11 +364,7 @@ int test() {
<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>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
@ -437,11 +427,7 @@ void test() {
<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>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
@ -462,11 +448,7 @@ void test() {
<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>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
@ -877,11 +859,7 @@ void test() {
<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>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
@ -1021,11 +999,7 @@ void test() {
<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>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">

View File

@ -47,6 +47,7 @@ for developer guidelines and send your questions and proposals to
<li><a href="#testing">Testing</a></li>
<li><a href="#commands">Useful Commands/Debugging Hints</a></li>
<li><a href="#additioninformation">Additional Sources of Information</a></li>
<li><a href="#links">Useful Links</a></li>
</ul>
<h2 id=start>Getting Started</h2>
@ -605,6 +606,11 @@ href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">video<
are available.
</ul>
<h2 id=links>Useful Links</h2>
<ul>
<li>The list of <a href="implicit_checks.html">Implicit Checkers</a></li>
</ul>
</div>
</div>
</body>

View File

@ -84,16 +84,17 @@ 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 thead div.example,
table.checkers thead td,
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 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; }
table.checkers ul, li { margin: 0 }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,165 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Implicit Checks</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 onload="initExpandCollapse()">
<div id="page">
<!--#include virtual="menu.html.incl"-->
<div id="content">
<h1>Implicit Checkers</h1>
Even though the implicit checkers do not produce any warnings, they are used to
support the analyzer core and model known APIs. See also
<a href = "available_checks.html">Default Checkers</a>
and <a href = "alpha_checks.html">Experimental (Alpha) Checkers</a>.
<ul>
<li><a href="#core_implicit_checkers">Core Implicit Checkers</a></li>
<li><a href="#osx_implicit_checkers">OS X Implicit Checkers</a></li>
</ul>
<!------------------------------- core implicit ------------------------------->
<h3 id="core_implicit_checkers">Core Implicit Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
core.DynamicTypePropagation</span><span class="lang">
(C++, ObjC)</span><div class="descr">
Generate dynamic type information.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C++
class A {
public:
A(int x) {}
virtual int foo();
};
class B: public A {
public:
B()
:A(foo())
// DynamicTypeInfo for 'this' rigion will wrap type 'A'
// unless the base constructor call expression is processed
{}
virtual int foo();
};
</pre></div><div class="separator"></div>
<div class="example"><pre>
// Objective-C
@interface MyClass : NSObject {}
@end
@implementation MyClass
+ (void)foo {
MyClass *x = [[self alloc] init];
// DynamicTypeInfo from a cast: from 'id' to 'MyClass *'
}
@end
void test() {
MyClass *x = [MyClass alloc];
// DynamicTypeInfo from a call to alloc:
// from 'id' to 'MyClass *'
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
core.builtin.BuiltinFunctions</span><span class="lang">
(C)</span><div class="descr">
Evaluate compiler builtin functions (e.g., <code>alloca()</code>)</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(int x) {
int *p = (int *)__builtin_alloca(8);
// evaluates to AllocaRegion
if(__builtin_expect(x > 10, 0)) // evaluates to 'x > 10'
x = 0;
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
core.builtin.NoReturnFunctions</span><span class="lang">
(C, ObjC)</span><div class="descr">
Evaluate "panic" functions that are known to not return to the caller.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
// C
void test() {
panic(); // generate sink
}
</pre></div><div class="separator"></div>
<div class="example"><pre>
// Objective-C
@interface MyObj : NSObject {}
- (void)foo;
@end
@implementation MyObj
- (void)foo {
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd
object:self
file:(@"somefile.m")
lineNumber:1
description:(@"some text")];
// generate sink
}
@end
</pre></div></div></td></tr>
</tbody></table>
<!---------------------------- OS X implicit ---------------------------------->
<h3 id="osx_implicit_checkers">OS X Implicit Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
<tbody>
<tr><td><div class="namedescr expandable"><span class="name">
osx.cocoa.Loops</span><span class="lang">
(ObjC)</span><div class="descr">
Improved modeling of loops using Cocoa collection types.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test() {
id x;
for (x in [NSArray testObject]) {
// assume the value of 'x' is non-nil
}
}
</pre></div></div></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">
osx.cocoa.NonNilReturnValue</span><span class="lang">
(ObjC)</span><div class="descr">
Model the APIs that are guaranteed to return a non-nil value.</div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
void test(NSArray *A) {
id subscriptObj = A[1]; // assume the value is non-nil
}
</pre></div></div></td></tr>
</tbody></table>
</div> <!-- page -->
</div> <!-- content -->
</body>
</html>

View File

@ -5,9 +5,10 @@
<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/expandcollapse.js"></script>
<script type="text/javascript" src="scripts/menu.js"></script>
</head>
<body>
<body onload="initExpandCollapse()">
<div id="page">
@ -470,11 +471,22 @@ int i = *p; // warn
<td class="aligned"></td></tr>
<!--<tr><td><div class="namedescr expandable"><span class="name">
<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.
Undefined behavior: the following usage of the pointer to the object whose
lifetime has ended can result in undefined behavior:<br>
The object will be or was of a class type with a non-trivial destructor and
<ul><li>the pointer is used as the operand of a delete-expression</li></ul>
The object will be or was of a non-POD class type (C++11: any class type) and
<ul><li>the pointer is used to access a non-static data member or call a
non-static member function of the object</li>
<li>the pointer is implicitly converted to a pointer to a base class
type</li>
<li>the pointer is used as the operand of a <code>static_cast</code> (except
when the conversion is to <code>void*</code>, or to <code>void*</code> and
subsequently to <code>char*</code>, or <code>unsigned char*</code>)</li>
<li>the pointer is used as the operand of a <code>dynamic_cast</code></li></ul>
<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>
@ -482,106 +494,90 @@ lifetime has ended can result in undefined behavior.
class A {
public:
int i;
};
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() {};
~A();
};
class B : public A {};
void test() {
B *b = new B;
new(b) A;
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
}
</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;
};
class B : public A {
public:
~B() {};
};
int test() {
A *a = new A;
new(a) B;
return a-&gt;i; // warn
delete a; // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;
class A {
public:
~A();
};
class B {};
void test() {
A *a = new A;
new(a) B;
a->~A();
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;
class A {
public:
~A();
};
class B : public A {};
class C {};
void f(A*);
void test() {
B *b = new B;
new(b) C;
f(b); // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;
class A {
public:
~A();
};
class B : public A {};
class C {};
A* test() {
B *b = new B;
new(b) C;
return static_cast&lt;A*&gt;(b); // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;
class A {
public:
~A();
};
class B : public A {};
class C {};
A* test() {
B *b = new B;
new(b) C;
return dynamic_cast&lt;A*&gt;(b); // warn
}
</pre></div></div></td>
<td class="aligned"></td></tr>-->
<td class="aligned"></td></tr>
<tr><td><div class="namedescr expandable"><span class="name">

View File

@ -0,0 +1,191 @@
// expand/collapse button (expander) is added if height of a cell content
// exceeds CLIP_HEIGHT px.
var CLIP_HEIGHT = 135;
// Height in pixels of an expander image.
var EXPANDER_HEIGHT = 13;
// Path to images for an expander.
var imgPath = "./images/expandcollapse/";
// array[group][cell] of { 'height', 'expanded' }.
// group: a number; cells of the same group belong to the same table row.
// cell: a number; unique index of a cell in a group.
// height: a number, px; original height of a cell in a table.
// expanded: boolean; is a cell expanded or collapsed?
var CellsInfo = [];
// Extracts group and cell indices from an id of the form identifier_group_cell.
function getCellIdx(id) {
var idx = id.substr(id.indexOf("_") + 1).split("_");
return { 'group': idx[0], 'cell': idx[1] };
}
// Returns { 'height', 'expanded' } info for a cell with a given id.
function getCellInfo(id) {
var idx = getCellIdx(id);
return CellsInfo[idx.group][idx.cell];
}
// Initialization, add nodes, collect info.
function initExpandCollapse() {
if (!document.getElementById)
return;
var groupCount = 0;
// Examine all table rows in the document.
var rows = document.body.getElementsByTagName("tr");
for (var i=0; i<rows.length; i+=1) {
var cellCount=0, newGroupCreated = false;
// Examine all divs in a table row.
var divs = rows[i].getElementsByTagName("div");
for (var j=0; j<divs.length; j+=1) {
var expandableDiv = divs[j];
if (expandableDiv.className.indexOf("expandable") == -1)
continue;
if (expandableDiv.offsetHeight <= CLIP_HEIGHT)
continue;
// We found a div wrapping a cell content whose height exceeds
// CLIP_HEIGHT.
var originalHeight = expandableDiv.offsetHeight;
// Unique postfix for ids for generated nodes for a given cell.
var idxStr = "_" + groupCount + "_" + cellCount;
// Create an expander and an additional wrapper for a cell content.
//
// --- expandableDiv ----
// --- expandableDiv --- | ------ data ------ |
// | cell content | -> | | cell content | |
// --------------------- | ------------------ |
// | ---- expander ---- |
// ----------------------
var data = document.createElement("div");
data.className = "data";
data.id = "data" + idxStr;
data.innerHTML = expandableDiv.innerHTML;
with (data.style) { height = (CLIP_HEIGHT - EXPANDER_HEIGHT) + "px";
overflow = "hidden" }
var expander = document.createElement("img");
with (expander.style) { display = "block"; paddingTop = "5px"; }
expander.src = imgPath + "ellipses_light.gif";
expander.id = "expander" + idxStr;
// Add mouse calbacks to expander.
expander.onclick = function() {
expandCollapse(this.id);
// Hack for Opera - onmouseout callback is not invoked when page
// content changes dinamically and mouse pointer goes out of an element.
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_light.gif"
: "ellipses_light.gif");
}
expander.onmouseover = function() {
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_dark.gif"
: "ellipses_dark.gif");
}
expander.onmouseout = function() {
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_light.gif"
: "ellipses_light.gif");
}
expandableDiv.innerHTML = "";
expandableDiv.appendChild(data);
expandableDiv.appendChild(expander);
expandableDiv.style.height = CLIP_HEIGHT + "px";
expandableDiv.id = "cell"+ idxStr;
// Keep original cell height and its ecpanded/cpllapsed state.
if (!newGroupCreated) {
CellsInfo[groupCount] = [];
newGroupCreated = true;
}
CellsInfo[groupCount][cellCount] = { 'height' : originalHeight,
'expanded' : false };
cellCount += 1;
}
groupCount += newGroupCreated ? 1 : 0;
}
}
function isElemTopVisible(elem) {
var body = document.body,
html = document.documentElement,
// Calculate expandableDiv absolute Y coordinate from the top of body.
bodyRect = body.getBoundingClientRect(),
elemRect = elem.getBoundingClientRect(),
elemOffset = Math.floor(elemRect.top - bodyRect.top),
// Calculate the absoute Y coordinate of visible area.
scrollTop = html.scrollTop || body && body.scrollTop || 0;
scrollTop -= html.clientTop; // IE<8
if (elemOffset < scrollTop)
return false;
return true;
}
// Invoked when an expander is pressed; expand/collapse a cell.
function expandCollapse(id) {
var cellInfo = getCellInfo(id);
var idx = getCellIdx(id);
// New height of a row.
var newHeight;
// Smart page scrolling may be done after collapse.
var mayNeedScroll;
if (cellInfo.expanded) {
// Cell is expanded - collapse the row height to CLIP_HEIGHT.
newHeight = CLIP_HEIGHT;
mayNeedScroll = true;
}
else {
// Cell is collapsed - expand the row height to the cells original height.
newHeight = cellInfo.height;
mayNeedScroll = false;
}
// Update all cells (height and expanded/collapsed state) in a row according
// to the new height of the row.
for (var i = 0; i < CellsInfo[idx.group].length; i++) {
var idxStr = "_" + idx.group + "_" + i;
var expandableDiv = document.getElementById("cell" + idxStr);
expandableDiv.style.height = newHeight + "px";
var data = document.getElementById("data" + idxStr);
var expander = document.getElementById("expander" + idxStr);
var state = CellsInfo[idx.group][i];
if (state.height > newHeight) {
// Cell height exceeds row height - collapse a cell.
data.style.height = (newHeight - EXPANDER_HEIGHT) + "px";
expander.src = imgPath + "ellipses_light.gif";
CellsInfo[idx.group][i].expanded = false;
} else {
// Cell height is less then or equal to row height - expand a cell.
data.style.height = "";
expander.src = imgPath + "arrows_light.gif";
CellsInfo[idx.group][i].expanded = true;
}
}
if (mayNeedScroll) {
var idxStr = "_" + idx.group + "_" + idx.cell;
var clickedExpandableDiv = document.getElementById("cell" + idxStr);
// Scroll page up if a row is collapsed and the rows top is above the
// viewport. The amount of scroll is the difference between a new and old
// row height.
if (!isElemTopVisible(clickedExpandableDiv)) {
window.scrollBy(0, newHeight - cellInfo.height);
}
}
}