diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /scripts/coccinelle/iterators | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'scripts/coccinelle/iterators')
-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 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Device node iterators put the previous value of the index variable, so an | ||
3 | /// explicit put causes a double put. | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2015 Julia Lawall, Inria. | ||
7 | // URL: http://coccinelle.lip6.fr/ | ||
8 | // Options: --no-includes --include-headers | ||
9 | // Requires: 1.0.4 | ||
10 | // Keywords: for_each_child_of_node, etc. | ||
11 | |||
12 | // This uses a conjunction, which requires at least coccinelle >= 1.0.4 | ||
13 | |||
14 | virtual patch | ||
15 | virtual context | ||
16 | virtual org | ||
17 | virtual report | ||
18 | |||
19 | @r exists@ | ||
20 | expression e1,e2; | ||
21 | local idexpression n; | ||
22 | iterator name for_each_node_by_name, for_each_node_by_type, | ||
23 | for_each_compatible_node, for_each_matching_node, | ||
24 | for_each_matching_node_and_match, for_each_child_of_node, | ||
25 | for_each_available_child_of_node, for_each_node_with_property; | ||
26 | iterator i; | ||
27 | position p1,p2; | ||
28 | statement S; | ||
29 | @@ | ||
30 | |||
31 | ( | ||
32 | ( | ||
33 | for_each_node_by_name(n,e1) S | ||
34 | | | ||
35 | for_each_node_by_type(n,e1) S | ||
36 | | | ||
37 | for_each_compatible_node(n,e1,e2) S | ||
38 | | | ||
39 | for_each_matching_node(n,e1) S | ||
40 | | | ||
41 | for_each_matching_node_and_match(n,e1,e2) S | ||
42 | | | ||
43 | for_each_child_of_node(e1,n) S | ||
44 | | | ||
45 | for_each_available_child_of_node(e1,n) S | ||
46 | | | ||
47 | for_each_node_with_property(n,e1) S | ||
48 | ) | ||
49 | & | ||
50 | i@p1(...) { | ||
51 | ... when != of_node_get(n) | ||
52 | when any | ||
53 | of_node_put@p2(n); | ||
54 | ... when any | ||
55 | } | ||
56 | ) | ||
57 | |||
58 | @s exists@ | ||
59 | local idexpression r.n; | ||
60 | statement S; | ||
61 | position r.p1,r.p2; | ||
62 | iterator i; | ||
63 | @@ | ||
64 | |||
65 | of_node_put@p2(n); | ||
66 | ... when any | ||
67 | i@p1(..., n, ...) | ||
68 | S | ||
69 | |||
70 | @t depends on s && patch && !context && !org && !report@ | ||
71 | local idexpression n; | ||
72 | position r.p2; | ||
73 | @@ | ||
74 | |||
75 | - of_node_put@p2(n); | ||
76 | |||
77 | // ---------------------------------------------------------------------------- | ||
78 | |||
79 | @t_context depends on s && !patch && (context || org || report)@ | ||
80 | local idexpression n; | ||
81 | position r.p2; | ||
82 | position j0; | ||
83 | @@ | ||
84 | |||
85 | * of_node_put@j0@p2(n); | ||
86 | |||
87 | // ---------------------------------------------------------------------------- | ||
88 | |||
89 | @script:python t_org depends on org@ | ||
90 | j0 << t_context.j0; | ||
91 | @@ | ||
92 | |||
93 | msg = "ERROR: probable double put." | ||
94 | coccilib.org.print_todo(j0[0], msg) | ||
95 | |||
96 | // ---------------------------------------------------------------------------- | ||
97 | |||
98 | @script:python t_report depends on report@ | ||
99 | j0 << t_context.j0; | ||
100 | @@ | ||
101 | |||
102 | msg = "ERROR: probable double put." | ||
103 | coccilib.report.print_report(j0[0], msg) | ||
104 | |||
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 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// These iterators only exit normally when the loop cursor is NULL, so there | ||
3 | /// is no point to call of_node_put on the final value. | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2010-2012 Nicolas Palix. | ||
7 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. | ||
8 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. | ||
9 | // URL: http://coccinelle.lip6.fr/ | ||
10 | // Comments: | ||
11 | // Options: --no-includes --include-headers | ||
12 | |||
13 | virtual patch | ||
14 | virtual context | ||
15 | virtual org | ||
16 | virtual report | ||
17 | |||
18 | @depends on patch@ | ||
19 | iterator name for_each_node_by_name; | ||
20 | expression np,E; | ||
21 | identifier l; | ||
22 | @@ | ||
23 | |||
24 | for_each_node_by_name(np,...) { | ||
25 | ... when != break; | ||
26 | when != goto l; | ||
27 | } | ||
28 | ... when != np = E | ||
29 | - of_node_put(np); | ||
30 | |||
31 | @depends on patch@ | ||
32 | iterator name for_each_node_by_type; | ||
33 | expression np,E; | ||
34 | identifier l; | ||
35 | @@ | ||
36 | |||
37 | for_each_node_by_type(np,...) { | ||
38 | ... when != break; | ||
39 | when != goto l; | ||
40 | } | ||
41 | ... when != np = E | ||
42 | - of_node_put(np); | ||
43 | |||
44 | @depends on patch@ | ||
45 | iterator name for_each_compatible_node; | ||
46 | expression np,E; | ||
47 | identifier l; | ||
48 | @@ | ||
49 | |||
50 | for_each_compatible_node(np,...) { | ||
51 | ... when != break; | ||
52 | when != goto l; | ||
53 | } | ||
54 | ... when != np = E | ||
55 | - of_node_put(np); | ||
56 | |||
57 | @depends on patch@ | ||
58 | iterator name for_each_matching_node; | ||
59 | expression np,E; | ||
60 | identifier l; | ||
61 | @@ | ||
62 | |||
63 | for_each_matching_node(np,...) { | ||
64 | ... when != break; | ||
65 | when != goto l; | ||
66 | } | ||
67 | ... when != np = E | ||
68 | - of_node_put(np); | ||
69 | |||
70 | // ---------------------------------------------------------------------- | ||
71 | |||
72 | @r depends on !patch forall@ | ||
73 | //iterator name for_each_node_by_name; | ||
74 | //iterator name for_each_node_by_type; | ||
75 | //iterator name for_each_compatible_node; | ||
76 | //iterator name for_each_matching_node; | ||
77 | expression np,E; | ||
78 | identifier l; | ||
79 | position p1,p2; | ||
80 | @@ | ||
81 | |||
82 | ( | ||
83 | *for_each_node_by_name@p1(np,...) | ||
84 | { | ||
85 | ... when != break; | ||
86 | when != goto l; | ||
87 | } | ||
88 | | | ||
89 | *for_each_node_by_type@p1(np,...) | ||
90 | { | ||
91 | ... when != break; | ||
92 | when != goto l; | ||
93 | } | ||
94 | | | ||
95 | *for_each_compatible_node@p1(np,...) | ||
96 | { | ||
97 | ... when != break; | ||
98 | when != goto l; | ||
99 | } | ||
100 | | | ||
101 | *for_each_matching_node@p1(np,...) | ||
102 | { | ||
103 | ... when != break; | ||
104 | when != goto l; | ||
105 | } | ||
106 | ) | ||
107 | ... when != np = E | ||
108 | * of_node_put@p2(np); | ||
109 | |||
110 | @script:python depends on org@ | ||
111 | p1 << r.p1; | ||
112 | p2 << r.p2; | ||
113 | @@ | ||
114 | |||
115 | cocci.print_main("unneeded of_node_put",p2) | ||
116 | cocci.print_secs("iterator",p1) | ||
117 | |||
118 | @script:python depends on report@ | ||
119 | p1 << r.p1; | ||
120 | p2 << r.p2; | ||
121 | @@ | ||
122 | |||
123 | msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line) | ||
124 | 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 @@ | |||
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) | ||
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 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Many iterators have the property that the first argument is always bound | ||
3 | /// to a real list element, never NULL. | ||
4 | //# False positives arise for some iterators that do not have this property, | ||
5 | //# or in cases when the loop cursor is reassigned. The latter should only | ||
6 | //# happen when the matched code is on the way to a loop exit (break, goto, | ||
7 | //# or return). | ||
8 | /// | ||
9 | // Confidence: Moderate | ||
10 | // Copyright: (C) 2010-2012 Nicolas Palix. | ||
11 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. | ||
12 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. | ||
13 | // URL: http://coccinelle.lip6.fr/ | ||
14 | // Comments: | ||
15 | // Options: --no-includes --include-headers | ||
16 | |||
17 | virtual patch | ||
18 | virtual context | ||
19 | virtual org | ||
20 | virtual report | ||
21 | |||
22 | @depends on patch@ | ||
23 | iterator I; | ||
24 | expression x,E,E1,E2; | ||
25 | statement S,S1,S2; | ||
26 | @@ | ||
27 | |||
28 | I(x,...) { <... | ||
29 | ( | ||
30 | - if (x == NULL && ...) S | ||
31 | | | ||
32 | - if (x != NULL || ...) | ||
33 | S | ||
34 | | | ||
35 | - (x == NULL) || | ||
36 | E | ||
37 | | | ||
38 | - (x != NULL) && | ||
39 | E | ||
40 | | | ||
41 | - (x == NULL && ...) ? E1 : | ||
42 | E2 | ||
43 | | | ||
44 | - (x != NULL || ...) ? | ||
45 | E1 | ||
46 | - : E2 | ||
47 | | | ||
48 | - if (x == NULL && ...) S1 else | ||
49 | S2 | ||
50 | | | ||
51 | - if (x != NULL || ...) | ||
52 | S1 | ||
53 | - else S2 | ||
54 | | | ||
55 | + BAD( | ||
56 | x == NULL | ||
57 | + ) | ||
58 | | | ||
59 | + BAD( | ||
60 | x != NULL | ||
61 | + ) | ||
62 | ) | ||
63 | ...> } | ||
64 | |||
65 | @r depends on !patch exists@ | ||
66 | iterator I; | ||
67 | expression x,E; | ||
68 | position p1,p2; | ||
69 | @@ | ||
70 | |||
71 | *I@p1(x,...) | ||
72 | { ... when != x = E | ||
73 | ( | ||
74 | * x@p2 == NULL | ||
75 | | | ||
76 | * x@p2 != NULL | ||
77 | ) | ||
78 | ... when any | ||
79 | } | ||
80 | |||
81 | @script:python depends on org@ | ||
82 | p1 << r.p1; | ||
83 | p2 << r.p2; | ||
84 | @@ | ||
85 | |||
86 | cocci.print_main("iterator-bound variable",p1) | ||
87 | cocci.print_secs("useless NULL test",p2) | ||
88 | |||
89 | @script:python depends on report@ | ||
90 | p1 << r.p1; | ||
91 | p2 << r.p2; | ||
92 | @@ | ||
93 | |||
94 | msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line) | ||
95 | 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 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// list_for_each_entry uses its first argument to get from one element of | ||
3 | /// the list to the next, so it is usually not a good idea to reassign it. | ||
4 | /// The first rule finds such a reassignment and the second rule checks | ||
5 | /// that there is a path from the reassignment back to the top of the loop. | ||
6 | /// | ||
7 | // Confidence: High | ||
8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. | ||
9 | // Copyright: (C) 2010 Julia Lawall, DIKU. | ||
10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. | ||
11 | // URL: http://coccinelle.lip6.fr/ | ||
12 | // Comments: | ||
13 | // Options: --no-includes --include-headers | ||
14 | |||
15 | virtual context | ||
16 | virtual org | ||
17 | virtual report | ||
18 | |||
19 | @r exists@ | ||
20 | iterator name list_for_each_entry; | ||
21 | expression x,E; | ||
22 | position p1,p2; | ||
23 | @@ | ||
24 | |||
25 | list_for_each_entry@p1(x,...) { <... x =@p2 E ...> } | ||
26 | |||
27 | @depends on context && !org && !report@ | ||
28 | expression x,E; | ||
29 | position r.p1,r.p2; | ||
30 | statement S; | ||
31 | @@ | ||
32 | |||
33 | *x =@p2 E | ||
34 | ... | ||
35 | list_for_each_entry@p1(x,...) S | ||
36 | |||
37 | // ------------------------------------------------------------------------ | ||
38 | |||
39 | @back depends on (org || report) && !context exists@ | ||
40 | expression x,E; | ||
41 | position r.p1,r.p2; | ||
42 | statement S; | ||
43 | @@ | ||
44 | |||
45 | x =@p2 E | ||
46 | ... | ||
47 | list_for_each_entry@p1(x,...) S | ||
48 | |||
49 | @script:python depends on back && org@ | ||
50 | p1 << r.p1; | ||
51 | p2 << r.p2; | ||
52 | @@ | ||
53 | |||
54 | cocci.print_main("iterator",p1) | ||
55 | cocci.print_secs("update",p2) | ||
56 | |||
57 | @script:python depends on back && report@ | ||
58 | p1 << r.p1; | ||
59 | p2 << r.p2; | ||
60 | @@ | ||
61 | |||
62 | msg = "iterator with update on line %s" % (p2[0].line) | ||
63 | 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 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// If list_for_each_entry, etc complete a traversal of the list, the iterator | ||
3 | /// variable ends up pointing to an address at an offset from the list head, | ||
4 | /// and not a meaningful structure. Thus this value should not be used after | ||
5 | /// the end of the iterator. | ||
6 | //#False positives arise when there is a goto in the iterator and the | ||
7 | //#reported reference is at the label of this goto. Some flag tests | ||
8 | //#may also cause a report to be a false positive. | ||
9 | /// | ||
10 | // Confidence: Moderate | ||
11 | // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. | ||
12 | // Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. | ||
13 | // URL: http://coccinelle.lip6.fr/ | ||
14 | // Comments: | ||
15 | // Options: --no-includes --include-headers | ||
16 | |||
17 | virtual context | ||
18 | virtual org | ||
19 | virtual report | ||
20 | |||
21 | @r exists@ | ||
22 | identifier c,member; | ||
23 | expression E,x; | ||
24 | iterator name list_for_each_entry; | ||
25 | iterator name list_for_each_entry_reverse; | ||
26 | iterator name list_for_each_entry_continue; | ||
27 | iterator name list_for_each_entry_continue_reverse; | ||
28 | iterator name list_for_each_entry_from; | ||
29 | iterator name list_for_each_entry_safe; | ||
30 | iterator name list_for_each_entry_safe_continue; | ||
31 | iterator name list_for_each_entry_safe_from; | ||
32 | iterator name list_for_each_entry_safe_reverse; | ||
33 | iterator name hlist_for_each_entry; | ||
34 | iterator name hlist_for_each_entry_continue; | ||
35 | iterator name hlist_for_each_entry_from; | ||
36 | iterator name hlist_for_each_entry_safe; | ||
37 | statement S; | ||
38 | position p1,p2; | ||
39 | type T; | ||
40 | @@ | ||
41 | |||
42 | ( | ||
43 | list_for_each_entry@p1(c,...,member) { ... when != break; | ||
44 | when forall | ||
45 | when strict | ||
46 | } | ||
47 | | | ||
48 | list_for_each_entry_reverse@p1(c,...,member) { ... when != break; | ||
49 | when forall | ||
50 | when strict | ||
51 | } | ||
52 | | | ||
53 | list_for_each_entry_continue@p1(c,...,member) { ... when != break; | ||
54 | when forall | ||
55 | when strict | ||
56 | } | ||
57 | | | ||
58 | list_for_each_entry_continue_reverse@p1(c,...,member) { ... when != break; | ||
59 | when forall | ||
60 | when strict | ||
61 | } | ||
62 | | | ||
63 | list_for_each_entry_from@p1(c,...,member) { ... when != break; | ||
64 | when forall | ||
65 | when strict | ||
66 | } | ||
67 | | | ||
68 | list_for_each_entry_safe@p1(c,...,member) { ... when != break; | ||
69 | when forall | ||
70 | when strict | ||
71 | } | ||
72 | | | ||
73 | list_for_each_entry_safe_continue@p1(c,...,member) { ... when != break; | ||
74 | when forall | ||
75 | when strict | ||
76 | } | ||
77 | | | ||
78 | list_for_each_entry_safe_from@p1(c,...,member) { ... when != break; | ||
79 | when forall | ||
80 | when strict | ||
81 | } | ||
82 | | | ||
83 | list_for_each_entry_safe_reverse@p1(c,...,member) { ... when != break; | ||
84 | when forall | ||
85 | when strict | ||
86 | } | ||
87 | ) | ||
88 | ... | ||
89 | ( | ||
90 | list_for_each_entry(c,...) S | ||
91 | | | ||
92 | list_for_each_entry_reverse(c,...) S | ||
93 | | | ||
94 | list_for_each_entry_continue(c,...) S | ||
95 | | | ||
96 | list_for_each_entry_continue_reverse(c,...) S | ||
97 | | | ||
98 | list_for_each_entry_from(c,...) S | ||
99 | | | ||
100 | list_for_each_entry_safe(c,...) S | ||
101 | | | ||
102 | list_for_each_entry_safe(x,c,...) S | ||
103 | | | ||
104 | list_for_each_entry_safe_continue(c,...) S | ||
105 | | | ||
106 | list_for_each_entry_safe_continue(x,c,...) S | ||
107 | | | ||
108 | list_for_each_entry_safe_from(c,...) S | ||
109 | | | ||
110 | list_for_each_entry_safe_from(x,c,...) S | ||
111 | | | ||
112 | list_for_each_entry_safe_reverse(c,...) S | ||
113 | | | ||
114 | list_for_each_entry_safe_reverse(x,c,...) S | ||
115 | | | ||
116 | hlist_for_each_entry(c,...) S | ||
117 | | | ||
118 | hlist_for_each_entry_continue(c,...) S | ||
119 | | | ||
120 | hlist_for_each_entry_from(c,...) S | ||
121 | | | ||
122 | hlist_for_each_entry_safe(c,...) S | ||
123 | | | ||
124 | list_remove_head(x,c,...) | ||
125 | | | ||
126 | sizeof(<+...c...+>) | ||
127 | | | ||
128 | &c->member | ||
129 | | | ||
130 | T c; | ||
131 | | | ||
132 | c = E | ||
133 | | | ||
134 | *c@p2 | ||
135 | ) | ||
136 | |||
137 | @script:python depends on org@ | ||
138 | p1 << r.p1; | ||
139 | p2 << r.p2; | ||
140 | @@ | ||
141 | |||
142 | cocci.print_main("invalid iterator index reference",p2) | ||
143 | cocci.print_secs("iterator",p1) | ||
144 | |||
145 | @script:python depends on report@ | ||
146 | p1 << r.p1; | ||
147 | p2 << r.p2; | ||
148 | @@ | ||
149 | |||
150 | msg = "ERROR: invalid reference to the index variable of the iterator on line %s" % (p1[0].line) | ||
151 | coccilib.report.print_report(p2[0], msg) | ||