| <!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 = &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> |
| |
| </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->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 <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> |
| |
| </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> |