diff options
Diffstat (limited to '')
-rw-r--r-- | scripts/coccinelle/iterators/device_node_continue.cocci | 104 | ||||
-rw-r--r-- | scripts/coccinelle/iterators/fen.cocci | 124 | ||||
-rw-r--r-- | scripts/coccinelle/iterators/for_each_child.cocci | 358 | ||||
-rw-r--r-- | scripts/coccinelle/iterators/itnull.cocci | 95 | ||||
-rw-r--r-- | scripts/coccinelle/iterators/list_entry_update.cocci | 63 | ||||
-rw-r--r-- | scripts/coccinelle/iterators/use_after_iter.cocci | 151 |
6 files changed, 895 insertions, 0 deletions
diff --git a/scripts/coccinelle/iterators/device_node_continue.cocci b/scripts/coccinelle/iterators/device_node_continue.cocci new file mode 100644 index 000000000..f8cd14dfa --- /dev/null +++ b/scripts/coccinelle/iterators/device_node_continue.cocci @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Device node iterators put the previous value of the index variable, so an +/// explicit put causes a double put. +/// +// Confidence: High +// Copyright: (C) 2015 Julia Lawall, Inria. +// URL: http://coccinelle.lip6.fr/ +// Options: --no-includes --include-headers +// Requires: 1.0.4 +// Keywords: for_each_child_of_node, etc. + +// This uses a conjunction, which requires at least coccinelle >= 1.0.4 + +virtual patch +virtual context +virtual org +virtual report + +@r exists@ +expression e1,e2; +local idexpression n; +iterator name for_each_node_by_name, for_each_node_by_type, +for_each_compatible_node, for_each_matching_node, +for_each_matching_node_and_match, for_each_child_of_node, +for_each_available_child_of_node, for_each_node_with_property; +iterator i; +position p1,p2; +statement S; +@@ + +( +( +for_each_node_by_name(n,e1) S +| +for_each_node_by_type(n,e1) S +| +for_each_compatible_node(n,e1,e2) S +| +for_each_matching_node(n,e1) S +| +for_each_matching_node_and_match(n,e1,e2) S +| +for_each_child_of_node(e1,n) S +| +for_each_available_child_of_node(e1,n) S +| +for_each_node_with_property(n,e1) S +) +& +i@p1(...) { + ... when != of_node_get(n) + when any + of_node_put@p2(n); + ... when any +} +) + +@s exists@ +local idexpression r.n; +statement S; +position r.p1,r.p2; +iterator i; +@@ + + of_node_put@p2(n); + ... when any + i@p1(..., n, ...) + S + +@t depends on s && patch && !context && !org && !report@ +local idexpression n; +position r.p2; +@@ + +- of_node_put@p2(n); + +// ---------------------------------------------------------------------------- + +@t_context depends on s && !patch && (context || org || report)@ +local idexpression n; +position r.p2; +position j0; +@@ + +* of_node_put@j0@p2(n); + +// ---------------------------------------------------------------------------- + +@script:python t_org depends on org@ +j0 << t_context.j0; +@@ + +msg = "ERROR: probable double put." +coccilib.org.print_todo(j0[0], msg) + +// ---------------------------------------------------------------------------- + +@script:python t_report depends on report@ +j0 << t_context.j0; +@@ + +msg = "ERROR: probable double put." +coccilib.report.print_report(j0[0], msg) + diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci new file mode 100644 index 000000000..b69f9665f --- /dev/null +++ b/scripts/coccinelle/iterators/fen.cocci @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// These iterators only exit normally when the loop cursor is NULL, so there +/// is no point to call of_node_put on the final value. +/// +// Confidence: High +// Copyright: (C) 2010-2012 Nicolas Palix. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on patch@ +iterator name for_each_node_by_name; +expression np,E; +identifier l; +@@ + +for_each_node_by_name(np,...) { + ... when != break; + when != goto l; +} +... when != np = E +- of_node_put(np); + +@depends on patch@ +iterator name for_each_node_by_type; +expression np,E; +identifier l; +@@ + +for_each_node_by_type(np,...) { + ... when != break; + when != goto l; +} +... when != np = E +- of_node_put(np); + +@depends on patch@ +iterator name for_each_compatible_node; +expression np,E; +identifier l; +@@ + +for_each_compatible_node(np,...) { + ... when != break; + when != goto l; +} +... when != np = E +- of_node_put(np); + +@depends on patch@ +iterator name for_each_matching_node; +expression np,E; +identifier l; +@@ + +for_each_matching_node(np,...) { + ... when != break; + when != goto l; +} +... when != np = E +- of_node_put(np); + +// ---------------------------------------------------------------------- + +@r depends on !patch forall@ +//iterator name for_each_node_by_name; +//iterator name for_each_node_by_type; +//iterator name for_each_compatible_node; +//iterator name for_each_matching_node; +expression np,E; +identifier l; +position p1,p2; +@@ + +( +*for_each_node_by_name@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_node_by_type@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_compatible_node@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_matching_node@p1(np,...) +{ + ... when != break; + when != goto l; +} +) +... when != np = E +* of_node_put@p2(np); + +@script:python depends on org@ +p1 << r.p1; +p2 << r.p2; +@@ + +cocci.print_main("unneeded of_node_put",p2) +cocci.print_secs("iterator",p1) + +@script:python depends on report@ +p1 << r.p1; +p2 << r.p2; +@@ + +msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line) +coccilib.report.print_report(p2[0], msg) diff --git a/scripts/coccinelle/iterators/for_each_child.cocci b/scripts/coccinelle/iterators/for_each_child.cocci new file mode 100644 index 000000000..bc3946159 --- /dev/null +++ b/scripts/coccinelle/iterators/for_each_child.cocci @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Adds missing of_node_put() before return/break/goto statement within a for_each iterator for child nodes. +//# False positives can be due to function calls within the for_each +//# loop that may encapsulate an of_node_put. +/// +// Confidence: High +// Copyright: (C) 2020 Sumera Priyadarsini +// URL: http://coccinelle.lip6.fr +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@r@ +local idexpression n; +expression e1,e2; +iterator name for_each_node_by_name, for_each_node_by_type, +for_each_compatible_node, for_each_matching_node, +for_each_matching_node_and_match, for_each_child_of_node, +for_each_available_child_of_node, for_each_node_with_property; +iterator i; +statement S; +expression list [n1] es; +@@ + +( +( +for_each_node_by_name(n,e1) S +| +for_each_node_by_type(n,e1) S +| +for_each_compatible_node(n,e1,e2) S +| +for_each_matching_node(n,e1) S +| +for_each_matching_node_and_match(n,e1,e2) S +| +for_each_child_of_node(e1,n) S +| +for_each_available_child_of_node(e1,n) S +| +for_each_node_with_property(n,e1) S +) +& +i(es,n,...) S +) + +@ruleone depends on patch && !context && !org && !report@ + +local idexpression r.n; +iterator r.i,i1; +expression e; +expression list [r.n1] es; +statement S; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + return n; +| + i1(...,n,...) S +| +- return of_node_get(n); ++ return n; +| ++ of_node_put(n); +? return ...; +) + ... when any + } + +@ruletwo depends on patch && !context && !org && !report@ + +local idexpression r.n; +iterator r.i,i1,i2; +expression e,e1; +expression list [r.n1] es; +statement S,S2; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| ++ of_node_put(n); +? break; +) + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree depends on patch && !context && !org && !report exists@ + +local idexpression r.n; +iterator r.i,i1,i2; +expression e,e1; +identifier l; +expression list [r.n1] es; +statement S,S2; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| ++ of_node_put(n); +? goto l; +) + ... when any + } +... when exists +l: ... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +// ---------------------------------------------------------------------------- + +@ruleone_context depends on !patch && (context || org || report) exists@ +statement S; +expression e; +expression list[r.n1] es; +iterator r.i, i1; +local idexpression r.n; +position j0, j1; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + return n; +| + i1(...,n,...) S +| + return @j1 ...; +) + ... when any + } + +@ruleone_disj depends on !patch && (context || org || report)@ +expression list[r.n1] es; +iterator r.i; +local idexpression r.n; +position ruleone_context.j0, ruleone_context.j1; +@@ + +* i@j0(es,n,...) { + ... +*return @j1...; + ... when any + } + +@ruletwo_context depends on !patch && (context || org || report) exists@ +statement S, S2; +expression e, e1; +expression list[r.n1] es; +iterator r.i, i1, i2; +local idexpression r.n; +position j0, j2; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| + break@j2; +) + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@ruletwo_disj depends on !patch && (context || org || report)@ +statement S2; +expression e1; +expression list[r.n1] es; +iterator r.i, i2; +local idexpression r.n; +position ruletwo_context.j0, ruletwo_context.j2; +@@ + +* i@j0(es,n,...) { + ... +*break @j2; + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree_context depends on !patch && (context || org || report) exists@ +identifier l; +statement S,S2; +expression e, e1; +expression list[r.n1] es; +iterator r.i, i1, i2; +local idexpression r.n; +position j0, j3; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| + goto l@j3; +) + ... when any + } +... when exists +l: +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree_disj depends on !patch && (context || org || report) exists@ +identifier l; +statement S2; +expression e1; +expression list[r.n1] es; +iterator r.i, i2; +local idexpression r.n; +position rulethree_context.j0, rulethree_context.j3; +@@ + +* i@j0(es,n,...) { + ... +*goto l@j3; + ... when any + } +... when exists + l: + ... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +// ---------------------------------------------------------------------------- + +@script:python ruleone_org depends on org@ +i << r.i; +j0 << ruleone_context.j0; +j1 << ruleone_context. j1; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before return " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j1[0], "") + +@script:python ruletwo_org depends on org@ +i << r.i; +j0 << ruletwo_context.j0; +j2 << ruletwo_context.j2; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before break " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j2[0], "") + +@script:python rulethree_org depends on org@ +i << r.i; +j0 << rulethree_context.j0; +j3 << rulethree_context.j3; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before goto " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j3[0], "") + +// ---------------------------------------------------------------------------- + +@script:python ruleone_report depends on report@ +i << r.i; +j0 << ruleone_context.j0; +j1 << ruleone_context.j1; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before return around line %s." % (i, j1[0].line) +coccilib.report.print_report(j0[0], msg) + +@script:python ruletwo_report depends on report@ +i << r.i; +j0 << ruletwo_context.j0; +j2 << ruletwo_context.j2; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before break around line %s." % (i,j2[0].line) +coccilib.report.print_report(j0[0], msg) + +@script:python rulethree_report depends on report@ +i << r.i; +j0 << rulethree_context.j0; +j3 << rulethree_context.j3; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before goto around lines %s." % (i,j3[0].line) +coccilib.report.print_report(j0[0], msg) diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci new file mode 100644 index 000000000..9b362b98d --- /dev/null +++ b/scripts/coccinelle/iterators/itnull.cocci @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// 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. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. +// 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) diff --git a/scripts/coccinelle/iterators/list_entry_update.cocci b/scripts/coccinelle/iterators/list_entry_update.cocci new file mode 100644 index 000000000..d62e8a160 --- /dev/null +++ b/scripts/coccinelle/iterators/list_entry_update.cocci @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// 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. +// Copyright: (C) 2010 Julia Lawall, DIKU. +// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: --no-includes --include-headers + +virtual context +virtual org +virtual report + +@r exists@ +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) diff --git a/scripts/coccinelle/iterators/use_after_iter.cocci b/scripts/coccinelle/iterators/use_after_iter.cocci new file mode 100644 index 000000000..9be48b520 --- /dev/null +++ b/scripts/coccinelle/iterators/use_after_iter.cocci @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// 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. +// Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. +// 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; +type T; +@@ + +( +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 +| +T c; +| +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) |