| // 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: https://coccinelle.gitlabpages.inria.fr/website |
| // 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) |