forked from OSchip/llvm-project
937 lines
26 KiB
HTML
937 lines
26 KiB
HTML
<!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="#clone_alpha_checkers">Clone Alpha Checkers</a></li>
|
|
<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="#valist_alpha_checkers">Variable Argument 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>
|
|
|
|
<!-- ============================= clone alpha ============================= -->
|
|
|
|
<h3 id="clone_alpha_checkers">Clone 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.clone.CloneChecker</span><span class="lang">
|
|
(C, C++, ObjC)</span><div class="descr">
|
|
Reports similar pieces of code.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
void log();
|
|
|
|
int max(int a, int b) { // warn
|
|
log();
|
|
if (a > b)
|
|
return a;
|
|
return b;
|
|
}
|
|
|
|
int maxClone(int x, int y) { // similar code here
|
|
log();
|
|
if (x > y)
|
|
return x;
|
|
return y;
|
|
}
|
|
</pre></div></div></td></tr>
|
|
</tbody></table>
|
|
|
|
<!-- ============================= 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.CallAndMessageUnInitRefArg</span><span class="lang">
|
|
(C, C++)</span><div class="descr">
|
|
Check for uninitialized arguments in function calls and Objective-C
|
|
message expressions.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
void test(void) {
|
|
int t;
|
|
int &p = t;
|
|
int &s = p;
|
|
int &q = s;
|
|
foo(q); // warn
|
|
}
|
|
</pre></div><div class="separator"></div>
|
|
<div class="example"><pre>
|
|
void test(void) {
|
|
int x;
|
|
foo(&x); // 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.Conversion</span><span class="lang">
|
|
(C, C++, ObjC)</span><div class="descr">
|
|
Loss of sign or precision in implicit conversions</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
void test(unsigned U, signed S) {
|
|
if (S > 10) {
|
|
if (U < S) {
|
|
}
|
|
}
|
|
if (S < -10) {
|
|
if (U < S) { // warn (loss of sign)
|
|
}
|
|
}
|
|
}
|
|
</pre></div><div class="separator"></div>
|
|
<div class="example"><pre>
|
|
void test() {
|
|
long long A = 1LL << 60;
|
|
short X = A; // warn (loss of precision)
|
|
}
|
|
</pre></div></div></td></tr>
|
|
|
|
|
|
<tr><td><div class="namedescr expandable"><span class="name">
|
|
alpha.core.DynamicTypeChecker</span><span class="lang">
|
|
(ObjC)</span><div class="descr">
|
|
Check for cases where the dynamic and the static type of an
|
|
object are unrelated.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
id date = [NSDate date];
|
|
|
|
// Warning: Object has a dynamic type 'NSDate *' which is
|
|
// incompatible with static type 'NSNumber *'"
|
|
NSNumber *number = date;
|
|
[number doubleValue];
|
|
</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 = &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 = &y - &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>
|
|
|
|
|
|
<tr><td><div class="namedescr expandable"><span class="name">
|
|
alpha.core.TestAfterDivZero</span><span class="lang">
|
|
(C, C++, ObjC)</span><div class="descr">
|
|
Check for division by variable that is later compared against 0.
|
|
Either the comparison is useless or there is division by zero.
|
|
</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
void test(int x) {
|
|
var = 77 / x;
|
|
if (x == 0) { } // warn
|
|
}
|
|
</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.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->f(); // warn
|
|
}
|
|
virtual void f();
|
|
};
|
|
</pre></div></div></td></tr>
|
|
|
|
</tbody></table>
|
|
|
|
|
|
|
|
<!-- =============================== va_list =============================== -->
|
|
<h3 id="valist_alpha_checkers">Variable Argument 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.valist.CopyToSelf</span><span class="lang">
|
|
(C)</span><div class="descr">
|
|
Calls to the <code>va_copy</code> macro should not copy onto itself.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
#include <stdarg.h>
|
|
|
|
void test(int x, ...) {
|
|
va_list args;
|
|
va_start(args, x);
|
|
va_copy(args, args); // warn
|
|
va_end(args);
|
|
}
|
|
</pre></div></div></td></tr>
|
|
|
|
<tr><td><div class="namedescr expandable"><span class="name">
|
|
alpha.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>.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
#include <stdarg.h>
|
|
|
|
void test(int x, ...) {
|
|
va_list args;
|
|
int y = va_arg(args, int); // warn
|
|
}
|
|
</pre></div>
|
|
<div class="example"><pre>
|
|
#include <stdarg.h>
|
|
|
|
void test(int x, ...) {
|
|
va_list args;
|
|
va_start(args, x);
|
|
va_end(args);
|
|
int z = va_arg(args, int); // warn
|
|
}
|
|
</pre></div></div></td></tr>
|
|
|
|
<tr><td><div class="namedescr expandable"><span class="name">
|
|
alpha.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.</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
#include <stdarg.h>
|
|
|
|
void test(int x, ...) {
|
|
va_list args;
|
|
va_start(args, x);
|
|
int y = x + va_arg(args, int);
|
|
} // warn: missing va_end
|
|
</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.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 <NSObject>
|
|
- (void) invalidate
|
|
__attribute__((annotate("objc_instance_variable_invalidator")));
|
|
@end
|
|
|
|
@interface InvalidationImpObj : NSObject <Invalidation>
|
|
@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 <NSObject>
|
|
- (void)invalidate
|
|
__attribute__((annotate("objc_instance_variable_invalidator")));
|
|
@end
|
|
|
|
@interface NeedInvalidation : NSObject <Invalidation>
|
|
@end
|
|
|
|
@interface MissingInvalidationMethodDecl : NSObject {
|
|
NeedInvalidation *Var; // warn
|
|
}
|
|
@end
|
|
|
|
@implementation MissingInvalidationMethodDecl
|
|
@end
|
|
</pre></div></div></td></tr>
|
|
|
|
|
|
<tr><td><div class="namedescr expandable"><span class="name">
|
|
alpha.osx.cocoa.localizability.PluralMisuseChecker</span><span class="lang">
|
|
(ObjC)</span><div class="descr">
|
|
Warns against using one vs. many plural pattern in code
|
|
when generating localized strings.
|
|
</div></div></td>
|
|
<td><div class="exampleContainer expandable">
|
|
<div class="example"><pre>
|
|
NSString *reminderText =
|
|
NSLocalizedString(@"None", @"Indicates no reminders");
|
|
if (reminderCount == 1) {
|
|
// Warning: Plural cases are not supported accross all languages.
|
|
// Use a .stringsdict file instead
|
|
reminderText =
|
|
NSLocalizedString(@"1 Reminder", @"Indicates single reminder");
|
|
} else if (reminderCount >= 2) {
|
|
// Warning: Plural cases are not supported accross all languages.
|
|
// Use a .stringsdict file instead
|
|
reminderText =
|
|
[NSString stringWithFormat:
|
|
NSLocalizedString(@"%@ Reminders", @"Indicates multiple reminders"),
|
|
reminderCount];
|
|
}
|
|
</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.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>
|