Skip to content

Commit 82c2d81

Browse files
SylfrenaJuliaLawall
authored andcommitted
coccinelle: iterators: Add for_each_child.cocci script
While iterating over child nodes with the for_each functions, if control is transferred from the middle of the loop, as in the case of a break or return or goto, there is no decrement in the reference counter thus ultimately resulting in a memory leak. Add this script to detect potential memory leaks caused by the absence of of_node_put() before break, goto, or, return statements which transfer control outside the loop. Signed-off-by: Sumera Priyadarsini <[email protected]> Signed-off-by: Julia Lawall <[email protected]>
1 parent c586456 commit 82c2d81

File tree

1 file changed

+358
-0
lines changed

1 file changed

+358
-0
lines changed
Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
// Adds missing of_node_put() before return/break/goto statement within a for_each iterator for child nodes.
3+
//# False positives can be due to function calls within the for_each
4+
//# loop that may encapsulate an of_node_put.
5+
///
6+
// Confidence: High
7+
// Copyright: (C) 2020 Sumera Priyadarsini
8+
// URL: http://coccinelle.lip6.fr
9+
// Options: --no-includes --include-headers
10+
11+
virtual patch
12+
virtual context
13+
virtual org
14+
virtual report
15+
16+
@r@
17+
local idexpression n;
18+
expression e1,e2;
19+
iterator name for_each_node_by_name, for_each_node_by_type,
20+
for_each_compatible_node, for_each_matching_node,
21+
for_each_matching_node_and_match, for_each_child_of_node,
22+
for_each_available_child_of_node, for_each_node_with_property;
23+
iterator i;
24+
statement S;
25+
expression list [n1] es;
26+
@@
27+
28+
(
29+
(
30+
for_each_node_by_name(n,e1) S
31+
|
32+
for_each_node_by_type(n,e1) S
33+
|
34+
for_each_compatible_node(n,e1,e2) S
35+
|
36+
for_each_matching_node(n,e1) S
37+
|
38+
for_each_matching_node_and_match(n,e1,e2) S
39+
|
40+
for_each_child_of_node(e1,n) S
41+
|
42+
for_each_available_child_of_node(e1,n) S
43+
|
44+
for_each_node_with_property(n,e1) S
45+
)
46+
&
47+
i(es,n,...) S
48+
)
49+
50+
@ruleone depends on patch && !context && !org && !report@
51+
52+
local idexpression r.n;
53+
iterator r.i,i1;
54+
expression e;
55+
expression list [r.n1] es;
56+
statement S;
57+
@@
58+
59+
i(es,n,...) {
60+
...
61+
(
62+
of_node_put(n);
63+
|
64+
e = n
65+
|
66+
return n;
67+
|
68+
i1(...,n,...) S
69+
|
70+
- return of_node_get(n);
71+
+ return n;
72+
|
73+
+ of_node_put(n);
74+
? return ...;
75+
)
76+
... when any
77+
}
78+
79+
@ruletwo depends on patch && !context && !org && !report@
80+
81+
local idexpression r.n;
82+
iterator r.i,i1,i2;
83+
expression e,e1;
84+
expression list [r.n1] es;
85+
statement S,S2;
86+
@@
87+
88+
i(es,n,...) {
89+
...
90+
(
91+
of_node_put(n);
92+
|
93+
e = n
94+
|
95+
i1(...,n,...) S
96+
|
97+
+ of_node_put(n);
98+
? break;
99+
)
100+
... when any
101+
}
102+
... when != n
103+
when strict
104+
when forall
105+
(
106+
n = e1;
107+
|
108+
?i2(...,n,...) S2
109+
)
110+
111+
@rulethree depends on patch && !context && !org && !report exists@
112+
113+
local idexpression r.n;
114+
iterator r.i,i1,i2;
115+
expression e,e1;
116+
identifier l;
117+
expression list [r.n1] es;
118+
statement S,S2;
119+
@@
120+
121+
i(es,n,...) {
122+
...
123+
(
124+
of_node_put(n);
125+
|
126+
e = n
127+
|
128+
i1(...,n,...) S
129+
|
130+
+ of_node_put(n);
131+
? goto l;
132+
)
133+
... when any
134+
}
135+
... when exists
136+
l: ... when != n
137+
when strict
138+
when forall
139+
(
140+
n = e1;
141+
|
142+
?i2(...,n,...) S2
143+
)
144+
145+
// ----------------------------------------------------------------------------
146+
147+
@ruleone_context depends on !patch && (context || org || report) exists@
148+
statement S;
149+
expression e;
150+
expression list[r.n1] es;
151+
iterator r.i, i1;
152+
local idexpression r.n;
153+
position j0, j1;
154+
@@
155+
156+
i@j0(es,n,...) {
157+
...
158+
(
159+
of_node_put(n);
160+
|
161+
e = n
162+
|
163+
return n;
164+
|
165+
i1(...,n,...) S
166+
|
167+
return @j1 ...;
168+
)
169+
... when any
170+
}
171+
172+
@ruleone_disj depends on !patch && (context || org || report)@
173+
expression list[r.n1] es;
174+
iterator r.i;
175+
local idexpression r.n;
176+
position ruleone_context.j0, ruleone_context.j1;
177+
@@
178+
179+
* i@j0(es,n,...) {
180+
...
181+
*return @j1...;
182+
... when any
183+
}
184+
185+
@ruletwo_context depends on !patch && (context || org || report) exists@
186+
statement S, S2;
187+
expression e, e1;
188+
expression list[r.n1] es;
189+
iterator r.i, i1, i2;
190+
local idexpression r.n;
191+
position j0, j2;
192+
@@
193+
194+
i@j0(es,n,...) {
195+
...
196+
(
197+
of_node_put(n);
198+
|
199+
e = n
200+
|
201+
i1(...,n,...) S
202+
|
203+
break@j2;
204+
)
205+
... when any
206+
}
207+
... when != n
208+
when strict
209+
when forall
210+
(
211+
n = e1;
212+
|
213+
?i2(...,n,...) S2
214+
)
215+
216+
@ruletwo_disj depends on !patch && (context || org || report)@
217+
statement S2;
218+
expression e1;
219+
expression list[r.n1] es;
220+
iterator r.i, i2;
221+
local idexpression r.n;
222+
position ruletwo_context.j0, ruletwo_context.j2;
223+
@@
224+
225+
* i@j0(es,n,...) {
226+
...
227+
*break @j2;
228+
... when any
229+
}
230+
... when != n
231+
when strict
232+
when forall
233+
(
234+
n = e1;
235+
|
236+
?i2(...,n,...) S2
237+
)
238+
239+
@rulethree_context depends on !patch && (context || org || report) exists@
240+
identifier l;
241+
statement S,S2;
242+
expression e, e1;
243+
expression list[r.n1] es;
244+
iterator r.i, i1, i2;
245+
local idexpression r.n;
246+
position j0, j3;
247+
@@
248+
249+
i@j0(es,n,...) {
250+
...
251+
(
252+
of_node_put(n);
253+
|
254+
e = n
255+
|
256+
i1(...,n,...) S
257+
|
258+
goto l@j3;
259+
)
260+
... when any
261+
}
262+
... when exists
263+
l:
264+
... when != n
265+
when strict
266+
when forall
267+
(
268+
n = e1;
269+
|
270+
?i2(...,n,...) S2
271+
)
272+
273+
@rulethree_disj depends on !patch && (context || org || report) exists@
274+
identifier l;
275+
statement S2;
276+
expression e1;
277+
expression list[r.n1] es;
278+
iterator r.i, i2;
279+
local idexpression r.n;
280+
position rulethree_context.j0, rulethree_context.j3;
281+
@@
282+
283+
* i@j0(es,n,...) {
284+
...
285+
*goto l@j3;
286+
... when any
287+
}
288+
... when exists
289+
l:
290+
... when != n
291+
when strict
292+
when forall
293+
(
294+
n = e1;
295+
|
296+
?i2(...,n,...) S2
297+
)
298+
299+
// ----------------------------------------------------------------------------
300+
301+
@script:python ruleone_org depends on org@
302+
i << r.i;
303+
j0 << ruleone_context.j0;
304+
j1 << ruleone_context. j1;
305+
@@
306+
307+
msg = "WARNING: Function \"%s\" should have of_node_put() before return " % (i)
308+
coccilib.org.print_safe_todo(j0[0], msg)
309+
coccilib.org.print_link(j1[0], "")
310+
311+
@script:python ruletwo_org depends on org@
312+
i << r.i;
313+
j0 << ruletwo_context.j0;
314+
j2 << ruletwo_context.j2;
315+
@@
316+
317+
msg = "WARNING: Function \"%s\" should have of_node_put() before break " % (i)
318+
coccilib.org.print_safe_todo(j0[0], msg)
319+
coccilib.org.print_link(j2[0], "")
320+
321+
@script:python rulethree_org depends on org@
322+
i << r.i;
323+
j0 << rulethree_context.j0;
324+
j3 << rulethree_context.j3;
325+
@@
326+
327+
msg = "WARNING: Function \"%s\" should have of_node_put() before goto " % (i)
328+
coccilib.org.print_safe_todo(j0[0], msg)
329+
coccilib.org.print_link(j3[0], "")
330+
331+
// ----------------------------------------------------------------------------
332+
333+
@script:python ruleone_report depends on report@
334+
i << r.i;
335+
j0 << ruleone_context.j0;
336+
j1 << ruleone_context.j1;
337+
@@
338+
339+
msg = "WARNING: Function \"%s\" should have of_node_put() before return around line %s." % (i, j1[0].line)
340+
coccilib.report.print_report(j0[0], msg)
341+
342+
@script:python ruletwo_report depends on report@
343+
i << r.i;
344+
j0 << ruletwo_context.j0;
345+
j2 << ruletwo_context.j2;
346+
@@
347+
348+
msg = "WARNING: Function \"%s\" should have of_node_put() before break around line %s." % (i,j2[0].line)
349+
coccilib.report.print_report(j0[0], msg)
350+
351+
@script:python rulethree_report depends on report@
352+
i << r.i;
353+
j0 << rulethree_context.j0;
354+
j3 << rulethree_context.j3;
355+
@@
356+
357+
msg = "WARNING: Function \"%s\" should have of_node_put() before goto around lines %s." % (i,j3[0].line)
358+
coccilib.report.print_report(j0[0], msg)

0 commit comments

Comments
 (0)