Add some useful static code analysis scripts for coccinelle copied from the Linux kernel v4.14-rc8: Warn on check against NULL before calling free. scripts/coccinelle/free/ifnullfree.cocci Detect superfluous NULL check for list iterator. scripts/coccinelle/iterators/itnull.cocci Check if list iterator is reassigned. scripts/coccinelle/iterators/list_entry_update.cocci Check if list iterator is used after loop. scripts/coccinelle/iterators/use_after_iter.cocci Find wrong argument of sizeof in allocation function: scripts/coccinelle/misc/badty.cocci Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>master
parent
8a28caf02b
commit
06feb5d0bf
@ -0,0 +1,59 @@ |
|||||||
|
/// NULL check before some freeing functions is not needed. |
||||||
|
/// |
||||||
|
/// Based on checkpatch warning |
||||||
|
/// "kfree(NULL) is safe this check is probably not required" |
||||||
|
/// and kfreeaddr.cocci by Julia Lawall. |
||||||
|
/// |
||||||
|
// Copyright: (C) 2014 Fabian Frederick. GPLv2. |
||||||
|
// Comments: - |
||||||
|
// Options: --no-includes --include-headers |
||||||
|
|
||||||
|
virtual patch |
||||||
|
virtual org |
||||||
|
virtual report |
||||||
|
virtual context |
||||||
|
|
||||||
|
@r2 depends on patch@ |
||||||
|
expression E; |
||||||
|
@@ |
||||||
|
- if (E != NULL) |
||||||
|
( |
||||||
|
kfree(E); |
||||||
|
| |
||||||
|
kzfree(E); |
||||||
|
| |
||||||
|
debugfs_remove(E); |
||||||
|
| |
||||||
|
debugfs_remove_recursive(E); |
||||||
|
| |
||||||
|
usb_free_urb(E); |
||||||
|
| |
||||||
|
kmem_cache_destroy(E); |
||||||
|
| |
||||||
|
mempool_destroy(E); |
||||||
|
| |
||||||
|
dma_pool_destroy(E); |
||||||
|
) |
||||||
|
|
||||||
|
@r depends on context || report || org @ |
||||||
|
expression E; |
||||||
|
position p; |
||||||
|
@@ |
||||||
|
|
||||||
|
* if (E != NULL) |
||||||
|
* \(kfree@p\|kzfree@p\|debugfs_remove@p\|debugfs_remove_recursive@p\| |
||||||
|
* usb_free_urb@p\|kmem_cache_destroy@p\|mempool_destroy@p\| |
||||||
|
* dma_pool_destroy@p\)(E); |
||||||
|
|
||||||
|
@script:python depends on org@ |
||||||
|
p << r.p; |
||||||
|
@@ |
||||||
|
|
||||||
|
cocci.print_main("NULL check before that freeing function is not needed", p) |
||||||
|
|
||||||
|
@script:python depends on report@ |
||||||
|
p << r.p; |
||||||
|
@@ |
||||||
|
|
||||||
|
msg = "WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values." |
||||||
|
coccilib.report.print_report(p[0], msg) |
@ -0,0 +1,94 @@ |
|||||||
|
/// Many iterators have the property that the first argument is always bound |
||||||
|
/// to a real list element, never NULL. |
||||||
|
//# False positives arise for some iterators that do not have this property, |
||||||
|
//# or in cases when the loop cursor is reassigned. The latter should only |
||||||
|
//# happen when the matched code is on the way to a loop exit (break, goto, |
||||||
|
//# or return). |
||||||
|
/// |
||||||
|
// Confidence: Moderate |
||||||
|
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
||||||
|
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
||||||
|
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
||||||
|
// URL: http://coccinelle.lip6.fr/ |
||||||
|
// Comments: |
||||||
|
// Options: --no-includes --include-headers |
||||||
|
|
||||||
|
virtual patch |
||||||
|
virtual context |
||||||
|
virtual org |
||||||
|
virtual report |
||||||
|
|
||||||
|
@depends on patch@ |
||||||
|
iterator I; |
||||||
|
expression x,E,E1,E2; |
||||||
|
statement S,S1,S2; |
||||||
|
@@ |
||||||
|
|
||||||
|
I(x,...) { <... |
||||||
|
( |
||||||
|
- if (x == NULL && ...) S |
||||||
|
| |
||||||
|
- if (x != NULL || ...) |
||||||
|
S |
||||||
|
| |
||||||
|
- (x == NULL) || |
||||||
|
E |
||||||
|
| |
||||||
|
- (x != NULL) && |
||||||
|
E |
||||||
|
| |
||||||
|
- (x == NULL && ...) ? E1 : |
||||||
|
E2 |
||||||
|
| |
||||||
|
- (x != NULL || ...) ? |
||||||
|
E1 |
||||||
|
- : E2 |
||||||
|
| |
||||||
|
- if (x == NULL && ...) S1 else |
||||||
|
S2 |
||||||
|
| |
||||||
|
- if (x != NULL || ...) |
||||||
|
S1 |
||||||
|
- else S2 |
||||||
|
| |
||||||
|
+ BAD( |
||||||
|
x == NULL |
||||||
|
+ ) |
||||||
|
| |
||||||
|
+ BAD( |
||||||
|
x != NULL |
||||||
|
+ ) |
||||||
|
) |
||||||
|
...> } |
||||||
|
|
||||||
|
@r depends on !patch exists@ |
||||||
|
iterator I; |
||||||
|
expression x,E; |
||||||
|
position p1,p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
*I@p1(x,...) |
||||||
|
{ ... when != x = E |
||||||
|
( |
||||||
|
* x@p2 == NULL |
||||||
|
| |
||||||
|
* x@p2 != NULL |
||||||
|
) |
||||||
|
... when any |
||||||
|
} |
||||||
|
|
||||||
|
@script:python depends on org@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
cocci.print_main("iterator-bound variable",p1) |
||||||
|
cocci.print_secs("useless NULL test",p2) |
||||||
|
|
||||||
|
@script:python depends on report@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line) |
||||||
|
coccilib.report.print_report(p2[0], msg) |
@ -0,0 +1,62 @@ |
|||||||
|
/// list_for_each_entry uses its first argument to get from one element of |
||||||
|
/// the list to the next, so it is usually not a good idea to reassign it. |
||||||
|
/// The first rule finds such a reassignment and the second rule checks |
||||||
|
/// that there is a path from the reassignment back to the top of the loop. |
||||||
|
/// |
||||||
|
// Confidence: High |
||||||
|
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. |
||||||
|
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. |
||||||
|
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. |
||||||
|
// URL: http://coccinelle.lip6.fr/ |
||||||
|
// Comments: |
||||||
|
// Options: --no-includes --include-headers |
||||||
|
|
||||||
|
virtual context |
||||||
|
virtual org |
||||||
|
virtual report |
||||||
|
|
||||||
|
@r@ |
||||||
|
iterator name list_for_each_entry; |
||||||
|
expression x,E; |
||||||
|
position p1,p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
list_for_each_entry@p1(x,...) { <... x =@p2 E ...> } |
||||||
|
|
||||||
|
@depends on context && !org && !report@ |
||||||
|
expression x,E; |
||||||
|
position r.p1,r.p2; |
||||||
|
statement S; |
||||||
|
@@ |
||||||
|
|
||||||
|
*x =@p2 E |
||||||
|
... |
||||||
|
list_for_each_entry@p1(x,...) S |
||||||
|
|
||||||
|
// ------------------------------------------------------------------------ |
||||||
|
|
||||||
|
@back depends on (org || report) && !context exists@ |
||||||
|
expression x,E; |
||||||
|
position r.p1,r.p2; |
||||||
|
statement S; |
||||||
|
@@ |
||||||
|
|
||||||
|
x =@p2 E |
||||||
|
... |
||||||
|
list_for_each_entry@p1(x,...) S |
||||||
|
|
||||||
|
@script:python depends on back && org@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
cocci.print_main("iterator",p1) |
||||||
|
cocci.print_secs("update",p2) |
||||||
|
|
||||||
|
@script:python depends on back && report@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
msg = "iterator with update on line %s" % (p2[0].line) |
||||||
|
coccilib.report.print_report(p1[0],msg) |
@ -0,0 +1,147 @@ |
|||||||
|
/// If list_for_each_entry, etc complete a traversal of the list, the iterator |
||||||
|
/// variable ends up pointing to an address at an offset from the list head, |
||||||
|
/// and not a meaningful structure. Thus this value should not be used after |
||||||
|
/// the end of the iterator. |
||||||
|
//#False positives arise when there is a goto in the iterator and the |
||||||
|
//#reported reference is at the label of this goto. Some flag tests |
||||||
|
//#may also cause a report to be a false positive. |
||||||
|
/// |
||||||
|
// Confidence: Moderate |
||||||
|
// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. |
||||||
|
// Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. GPLv2. |
||||||
|
// URL: http://coccinelle.lip6.fr/ |
||||||
|
// Comments: |
||||||
|
// Options: --no-includes --include-headers |
||||||
|
|
||||||
|
virtual context |
||||||
|
virtual org |
||||||
|
virtual report |
||||||
|
|
||||||
|
@r exists@ |
||||||
|
identifier c,member; |
||||||
|
expression E,x; |
||||||
|
iterator name list_for_each_entry; |
||||||
|
iterator name list_for_each_entry_reverse; |
||||||
|
iterator name list_for_each_entry_continue; |
||||||
|
iterator name list_for_each_entry_continue_reverse; |
||||||
|
iterator name list_for_each_entry_from; |
||||||
|
iterator name list_for_each_entry_safe; |
||||||
|
iterator name list_for_each_entry_safe_continue; |
||||||
|
iterator name list_for_each_entry_safe_from; |
||||||
|
iterator name list_for_each_entry_safe_reverse; |
||||||
|
iterator name hlist_for_each_entry; |
||||||
|
iterator name hlist_for_each_entry_continue; |
||||||
|
iterator name hlist_for_each_entry_from; |
||||||
|
iterator name hlist_for_each_entry_safe; |
||||||
|
statement S; |
||||||
|
position p1,p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
( |
||||||
|
list_for_each_entry@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_reverse@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_continue@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_continue_reverse@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_from@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_safe@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_safe_continue@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_safe_from@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
| |
||||||
|
list_for_each_entry_safe_reverse@p1(c,...,member) { ... when != break; |
||||||
|
when forall |
||||||
|
when strict |
||||||
|
} |
||||||
|
) |
||||||
|
... |
||||||
|
( |
||||||
|
list_for_each_entry(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_reverse(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_continue(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_continue_reverse(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_from(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe(x,c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_continue(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_continue(x,c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_from(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_from(x,c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_reverse(c,...) S |
||||||
|
| |
||||||
|
list_for_each_entry_safe_reverse(x,c,...) S |
||||||
|
| |
||||||
|
hlist_for_each_entry(c,...) S |
||||||
|
| |
||||||
|
hlist_for_each_entry_continue(c,...) S |
||||||
|
| |
||||||
|
hlist_for_each_entry_from(c,...) S |
||||||
|
| |
||||||
|
hlist_for_each_entry_safe(c,...) S |
||||||
|
| |
||||||
|
list_remove_head(x,c,...) |
||||||
|
| |
||||||
|
sizeof(<+...c...+>) |
||||||
|
| |
||||||
|
&c->member |
||||||
|
| |
||||||
|
c = E |
||||||
|
| |
||||||
|
*c@p2 |
||||||
|
) |
||||||
|
|
||||||
|
@script:python depends on org@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
cocci.print_main("invalid iterator index reference",p2) |
||||||
|
cocci.print_secs("iterator",p1) |
||||||
|
|
||||||
|
@script:python depends on report@ |
||||||
|
p1 << r.p1; |
||||||
|
p2 << r.p2; |
||||||
|
@@ |
||||||
|
|
||||||
|
msg = "ERROR: invalid reference to the index variable of the iterator on line %s" % (p1[0].line) |
||||||
|
coccilib.report.print_report(p2[0], msg) |
@ -0,0 +1,76 @@ |
|||||||
|
/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element |
||||||
|
/// |
||||||
|
//# This makes an effort to find cases where the argument to sizeof is wrong |
||||||
|
//# in memory allocation functions by checking the type of the allocated memory |
||||||
|
//# when it is a double pointer and ensuring the sizeof argument takes a pointer |
||||||
|
//# to the the memory being allocated. There are false positives in cases the |
||||||
|
//# sizeof argument is not used in constructing the return value. The result |
||||||
|
//# may need some reformatting. |
||||||
|
// |
||||||
|
// Confidence: Moderate |
||||||
|
// Copyright: (C) 2014 Himangi Saraogi. GPLv2. |
||||||
|
// Comments: |
||||||
|
// Options: |
||||||
|
|
||||||
|
virtual patch |
||||||
|
virtual context |
||||||
|
virtual org |
||||||
|
virtual report |
||||||
|
|
||||||
|
//---------------------------------------------------------- |
||||||
|
// For context mode |
||||||
|
//---------------------------------------------------------- |
||||||
|
|
||||||
|
@depends on context disable sizeof_type_expr@ |
||||||
|
type T; |
||||||
|
T **x; |
||||||
|
@@ |
||||||
|
|
||||||
|
x = |
||||||
|
<+...sizeof( |
||||||
|
* T |
||||||
|
)...+> |
||||||
|
|
||||||
|
//---------------------------------------------------------- |
||||||
|
// For patch mode |
||||||
|
//---------------------------------------------------------- |
||||||
|
|
||||||
|
@depends on patch disable sizeof_type_expr@ |
||||||
|
type T; |
||||||
|
T **x; |
||||||
|
@@ |
||||||
|
|
||||||
|
x = |
||||||
|
<+...sizeof( |
||||||
|
- T |
||||||
|
+ *x |
||||||
|
)...+> |
||||||
|
|
||||||
|
//---------------------------------------------------------- |
||||||
|
// For org and report mode |
||||||
|
//---------------------------------------------------------- |
||||||
|
|
||||||
|
@r depends on (org || report) disable sizeof_type_expr@ |
||||||
|
type T; |
||||||
|
T **x; |
||||||
|
position p; |
||||||
|
@@ |
||||||
|
|
||||||
|
x = |
||||||
|
<+...sizeof( |
||||||
|
T@p |
||||||
|
)...+> |
||||||
|
|
||||||
|
@script:python depends on org@ |
||||||
|
p << r.p; |
||||||
|
@@ |
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type") |
||||||
|
|
||||||
|
@script:python depends on report@ |
||||||
|
p << r.p; |
||||||
|
@@ |
||||||
|
|
||||||
|
msg="WARNING: Use correct pointer type argument for sizeof" |
||||||
|
coccilib.report.print_report(p[0], msg) |
||||||
|
|
Loading…
Reference in new issue