Commit 408e057870c8680a50963b08f9f7efaa151a74ec
Exists in
master
and in
6 other branches
Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
* 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild: scripts/coccinelle: improve the coverage of some semantic patches coccinelle: semantic patches related to devm_ functions (part 2) coccinelle: semantic patches related to devm_ functions (part 1) coccinelle.txt: update documentation to include M= option coccicheck: add M= option to control which dir is processed ctags: remove struct forward declarations scripts/tags.sh: Add Page flag function magic
Showing 16 changed files Inline Diff
- Documentation/coccinelle.txt
- scripts/coccicheck
- scripts/coccinelle/api/devm_request_and_ioremap.cocci
- scripts/coccinelle/api/kstrdup.cocci
- scripts/coccinelle/api/memdup.cocci
- scripts/coccinelle/api/memdup_user.cocci
- scripts/coccinelle/free/devm_free.cocci
- scripts/coccinelle/free/kfree.cocci
- scripts/coccinelle/iterators/fen.cocci
- scripts/coccinelle/iterators/itnull.cocci
- scripts/coccinelle/locks/call_kern.cocci
- scripts/coccinelle/locks/flags.cocci
- scripts/coccinelle/locks/mini_lock.cocci
- scripts/coccinelle/misc/doubleinit.cocci
- scripts/coccinelle/null/eno.cocci
- scripts/tags.sh
Documentation/coccinelle.txt
1 | Copyright 2010 Nicolas Palix <npalix@diku.dk> | 1 | Copyright 2010 Nicolas Palix <npalix@diku.dk> |
2 | Copyright 2010 Julia Lawall <julia@diku.dk> | 2 | Copyright 2010 Julia Lawall <julia@diku.dk> |
3 | Copyright 2010 Gilles Muller <Gilles.Muller@lip6.fr> | 3 | Copyright 2010 Gilles Muller <Gilles.Muller@lip6.fr> |
4 | 4 | ||
5 | 5 | ||
6 | Getting Coccinelle | 6 | Getting Coccinelle |
7 | ~~~~~~~~~~~~~~~~~~~~ | 7 | ~~~~~~~~~~~~~~~~~~~~ |
8 | 8 | ||
9 | The semantic patches included in the kernel use the 'virtual rule' | 9 | The semantic patches included in the kernel use the 'virtual rule' |
10 | feature which was introduced in Coccinelle version 0.1.11. | 10 | feature which was introduced in Coccinelle version 0.1.11. |
11 | 11 | ||
12 | Coccinelle (>=0.2.0) is available through the package manager | 12 | Coccinelle (>=0.2.0) is available through the package manager |
13 | of many distributions, e.g. : | 13 | of many distributions, e.g. : |
14 | 14 | ||
15 | - Debian (>=squeeze) | 15 | - Debian (>=squeeze) |
16 | - Fedora (>=13) | 16 | - Fedora (>=13) |
17 | - Ubuntu (>=10.04 Lucid Lynx) | 17 | - Ubuntu (>=10.04 Lucid Lynx) |
18 | - OpenSUSE | 18 | - OpenSUSE |
19 | - Arch Linux | 19 | - Arch Linux |
20 | - NetBSD | 20 | - NetBSD |
21 | - FreeBSD | 21 | - FreeBSD |
22 | 22 | ||
23 | 23 | ||
24 | You can get the latest version released from the Coccinelle homepage at | 24 | You can get the latest version released from the Coccinelle homepage at |
25 | http://coccinelle.lip6.fr/ | 25 | http://coccinelle.lip6.fr/ |
26 | 26 | ||
27 | Information and tips about Coccinelle are also provided on the wiki | 27 | Information and tips about Coccinelle are also provided on the wiki |
28 | pages at http://cocci.ekstranet.diku.dk/wiki/doku.php | 28 | pages at http://cocci.ekstranet.diku.dk/wiki/doku.php |
29 | 29 | ||
30 | Once you have it, run the following command: | 30 | Once you have it, run the following command: |
31 | 31 | ||
32 | ./configure | 32 | ./configure |
33 | make | 33 | make |
34 | 34 | ||
35 | as a regular user, and install it with | 35 | as a regular user, and install it with |
36 | 36 | ||
37 | sudo make install | 37 | sudo make install |
38 | 38 | ||
39 | The semantic patches in the kernel will work best with Coccinelle version | 39 | The semantic patches in the kernel will work best with Coccinelle version |
40 | 0.2.4 or later. Using earlier versions may incur some parse errors in the | 40 | 0.2.4 or later. Using earlier versions may incur some parse errors in the |
41 | semantic patch code, but any results that are obtained should still be | 41 | semantic patch code, but any results that are obtained should still be |
42 | correct. | 42 | correct. |
43 | 43 | ||
44 | Using Coccinelle on the Linux kernel | 44 | Using Coccinelle on the Linux kernel |
45 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 45 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
46 | 46 | ||
47 | A Coccinelle-specific target is defined in the top level | 47 | A Coccinelle-specific target is defined in the top level |
48 | Makefile. This target is named 'coccicheck' and calls the 'coccicheck' | 48 | Makefile. This target is named 'coccicheck' and calls the 'coccicheck' |
49 | front-end in the 'scripts' directory. | 49 | front-end in the 'scripts' directory. |
50 | 50 | ||
51 | Four modes are defined: patch, report, context, and org. The mode to | 51 | Four modes are defined: patch, report, context, and org. The mode to |
52 | use is specified by setting the MODE variable with 'MODE=<mode>'. | 52 | use is specified by setting the MODE variable with 'MODE=<mode>'. |
53 | 53 | ||
54 | 'patch' proposes a fix, when possible. | 54 | 'patch' proposes a fix, when possible. |
55 | 55 | ||
56 | 'report' generates a list in the following format: | 56 | 'report' generates a list in the following format: |
57 | file:line:column-column: message | 57 | file:line:column-column: message |
58 | 58 | ||
59 | 'context' highlights lines of interest and their context in a | 59 | 'context' highlights lines of interest and their context in a |
60 | diff-like style.Lines of interest are indicated with '-'. | 60 | diff-like style.Lines of interest are indicated with '-'. |
61 | 61 | ||
62 | 'org' generates a report in the Org mode format of Emacs. | 62 | 'org' generates a report in the Org mode format of Emacs. |
63 | 63 | ||
64 | Note that not all semantic patches implement all modes. For easy use | 64 | Note that not all semantic patches implement all modes. For easy use |
65 | of Coccinelle, the default mode is "chain" which tries the previous | 65 | of Coccinelle, the default mode is "chain" which tries the previous |
66 | modes in the order above until one succeeds. | 66 | modes in the order above until one succeeds. |
67 | 67 | ||
68 | To make a report for every semantic patch, run the following command: | 68 | To make a report for every semantic patch, run the following command: |
69 | 69 | ||
70 | make coccicheck MODE=report | 70 | make coccicheck MODE=report |
71 | 71 | ||
72 | NB: The 'report' mode is the default one. | 72 | NB: The 'report' mode is the default one. |
73 | 73 | ||
74 | To produce patches, run: | 74 | To produce patches, run: |
75 | 75 | ||
76 | make coccicheck MODE=patch | 76 | make coccicheck MODE=patch |
77 | 77 | ||
78 | 78 | ||
79 | The coccicheck target applies every semantic patch available in the | 79 | The coccicheck target applies every semantic patch available in the |
80 | sub-directories of 'scripts/coccinelle' to the entire Linux kernel. | 80 | sub-directories of 'scripts/coccinelle' to the entire Linux kernel. |
81 | 81 | ||
82 | For each semantic patch, a commit message is proposed. It gives a | 82 | For each semantic patch, a commit message is proposed. It gives a |
83 | description of the problem being checked by the semantic patch, and | 83 | description of the problem being checked by the semantic patch, and |
84 | includes a reference to Coccinelle. | 84 | includes a reference to Coccinelle. |
85 | 85 | ||
86 | As any static code analyzer, Coccinelle produces false | 86 | As any static code analyzer, Coccinelle produces false |
87 | positives. Thus, reports must be carefully checked, and patches | 87 | positives. Thus, reports must be carefully checked, and patches |
88 | reviewed. | 88 | reviewed. |
89 | 89 | ||
90 | 90 | ||
91 | Using Coccinelle with a single semantic patch | 91 | Using Coccinelle with a single semantic patch |
92 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 92 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
93 | 93 | ||
94 | The optional make variable COCCI can be used to check a single | 94 | The optional make variable COCCI can be used to check a single |
95 | semantic patch. In that case, the variable must be initialized with | 95 | semantic patch. In that case, the variable must be initialized with |
96 | the name of the semantic patch to apply. | 96 | the name of the semantic patch to apply. |
97 | 97 | ||
98 | For instance: | 98 | For instance: |
99 | 99 | ||
100 | make coccicheck COCCI=<my_SP.cocci> MODE=patch | 100 | make coccicheck COCCI=<my_SP.cocci> MODE=patch |
101 | or | 101 | or |
102 | make coccicheck COCCI=<my_SP.cocci> MODE=report | 102 | make coccicheck COCCI=<my_SP.cocci> MODE=report |
103 | 103 | ||
104 | 104 | ||
105 | Using Coccinelle on (modified) files | 105 | Controlling Which Files are Processed by Coccinelle |
106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
107 | By default the entire kernel source tree is checked. | ||
107 | 108 | ||
109 | To apply Coccinelle to a specific directory, M= can be used. | ||
110 | For example, to check drivers/net/wireless/ one may write: | ||
111 | |||
112 | make coccicheck M=drivers/net/wireless/ | ||
113 | |||
108 | To apply Coccinelle on a file basis, instead of a directory basis, the | 114 | To apply Coccinelle on a file basis, instead of a directory basis, the |
109 | following command may be used: | 115 | following command may be used: |
110 | 116 | ||
111 | make C=1 CHECK="scripts/coccicheck" | 117 | make C=1 CHECK="scripts/coccicheck" |
112 | 118 | ||
113 | To check only newly edited code, use the value 2 for the C flag, i.e. | 119 | To check only newly edited code, use the value 2 for the C flag, i.e. |
114 | 120 | ||
115 | make C=2 CHECK="scripts/coccicheck" | 121 | make C=2 CHECK="scripts/coccicheck" |
116 | 122 | ||
117 | This runs every semantic patch in scripts/coccinelle by default. The | 123 | This runs every semantic patch in scripts/coccinelle by default. The |
118 | COCCI variable may additionally be used to only apply a single | 124 | COCCI variable may additionally be used to only apply a single |
119 | semantic patch as shown in the previous section. | 125 | semantic patch as shown in the previous section. |
120 | 126 | ||
121 | The "chain" mode is the default. You can select another one with the | 127 | The "chain" mode is the default. You can select another one with the |
122 | MODE variable explained above. | 128 | MODE variable explained above. |
123 | 129 | ||
124 | In this mode, there is no information about semantic patches | 130 | In this mode, there is no information about semantic patches |
125 | displayed, and no commit message proposed. | 131 | displayed, and no commit message proposed. |
126 | 132 | ||
127 | 133 | ||
128 | Proposing new semantic patches | 134 | Proposing new semantic patches |
129 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 135 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
130 | 136 | ||
131 | New semantic patches can be proposed and submitted by kernel | 137 | New semantic patches can be proposed and submitted by kernel |
132 | developers. For sake of clarity, they should be organized in the | 138 | developers. For sake of clarity, they should be organized in the |
133 | sub-directories of 'scripts/coccinelle/'. | 139 | sub-directories of 'scripts/coccinelle/'. |
134 | 140 | ||
135 | 141 | ||
136 | Detailed description of the 'report' mode | 142 | Detailed description of the 'report' mode |
137 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 143 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
138 | 144 | ||
139 | 'report' generates a list in the following format: | 145 | 'report' generates a list in the following format: |
140 | file:line:column-column: message | 146 | file:line:column-column: message |
141 | 147 | ||
142 | Example: | 148 | Example: |
143 | 149 | ||
144 | Running | 150 | Running |
145 | 151 | ||
146 | make coccicheck MODE=report COCCI=scripts/coccinelle/api/err_cast.cocci | 152 | make coccicheck MODE=report COCCI=scripts/coccinelle/api/err_cast.cocci |
147 | 153 | ||
148 | will execute the following part of the SmPL script. | 154 | will execute the following part of the SmPL script. |
149 | 155 | ||
150 | <smpl> | 156 | <smpl> |
151 | @r depends on !context && !patch && (org || report)@ | 157 | @r depends on !context && !patch && (org || report)@ |
152 | expression x; | 158 | expression x; |
153 | position p; | 159 | position p; |
154 | @@ | 160 | @@ |
155 | 161 | ||
156 | ERR_PTR@p(PTR_ERR(x)) | 162 | ERR_PTR@p(PTR_ERR(x)) |
157 | 163 | ||
158 | @script:python depends on report@ | 164 | @script:python depends on report@ |
159 | p << r.p; | 165 | p << r.p; |
160 | x << r.x; | 166 | x << r.x; |
161 | @@ | 167 | @@ |
162 | 168 | ||
163 | msg="ERR_CAST can be used with %s" % (x) | 169 | msg="ERR_CAST can be used with %s" % (x) |
164 | coccilib.report.print_report(p[0], msg) | 170 | coccilib.report.print_report(p[0], msg) |
165 | </smpl> | 171 | </smpl> |
166 | 172 | ||
167 | This SmPL excerpt generates entries on the standard output, as | 173 | This SmPL excerpt generates entries on the standard output, as |
168 | illustrated below: | 174 | illustrated below: |
169 | 175 | ||
170 | /home/user/linux/crypto/ctr.c:188:9-16: ERR_CAST can be used with alg | 176 | /home/user/linux/crypto/ctr.c:188:9-16: ERR_CAST can be used with alg |
171 | /home/user/linux/crypto/authenc.c:619:9-16: ERR_CAST can be used with auth | 177 | /home/user/linux/crypto/authenc.c:619:9-16: ERR_CAST can be used with auth |
172 | /home/user/linux/crypto/xts.c:227:9-16: ERR_CAST can be used with alg | 178 | /home/user/linux/crypto/xts.c:227:9-16: ERR_CAST can be used with alg |
173 | 179 | ||
174 | 180 | ||
175 | Detailed description of the 'patch' mode | 181 | Detailed description of the 'patch' mode |
176 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 182 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
177 | 183 | ||
178 | When the 'patch' mode is available, it proposes a fix for each problem | 184 | When the 'patch' mode is available, it proposes a fix for each problem |
179 | identified. | 185 | identified. |
180 | 186 | ||
181 | Example: | 187 | Example: |
182 | 188 | ||
183 | Running | 189 | Running |
184 | make coccicheck MODE=patch COCCI=scripts/coccinelle/api/err_cast.cocci | 190 | make coccicheck MODE=patch COCCI=scripts/coccinelle/api/err_cast.cocci |
185 | 191 | ||
186 | will execute the following part of the SmPL script. | 192 | will execute the following part of the SmPL script. |
187 | 193 | ||
188 | <smpl> | 194 | <smpl> |
189 | @ depends on !context && patch && !org && !report @ | 195 | @ depends on !context && patch && !org && !report @ |
190 | expression x; | 196 | expression x; |
191 | @@ | 197 | @@ |
192 | 198 | ||
193 | - ERR_PTR(PTR_ERR(x)) | 199 | - ERR_PTR(PTR_ERR(x)) |
194 | + ERR_CAST(x) | 200 | + ERR_CAST(x) |
195 | </smpl> | 201 | </smpl> |
196 | 202 | ||
197 | This SmPL excerpt generates patch hunks on the standard output, as | 203 | This SmPL excerpt generates patch hunks on the standard output, as |
198 | illustrated below: | 204 | illustrated below: |
199 | 205 | ||
200 | diff -u -p a/crypto/ctr.c b/crypto/ctr.c | 206 | diff -u -p a/crypto/ctr.c b/crypto/ctr.c |
201 | --- a/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200 | 207 | --- a/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200 |
202 | +++ b/crypto/ctr.c 2010-06-03 23:44:49.000000000 +0200 | 208 | +++ b/crypto/ctr.c 2010-06-03 23:44:49.000000000 +0200 |
203 | @@ -185,7 +185,7 @@ static struct crypto_instance *crypto_ct | 209 | @@ -185,7 +185,7 @@ static struct crypto_instance *crypto_ct |
204 | alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, | 210 | alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, |
205 | CRYPTO_ALG_TYPE_MASK); | 211 | CRYPTO_ALG_TYPE_MASK); |
206 | if (IS_ERR(alg)) | 212 | if (IS_ERR(alg)) |
207 | - return ERR_PTR(PTR_ERR(alg)); | 213 | - return ERR_PTR(PTR_ERR(alg)); |
208 | + return ERR_CAST(alg); | 214 | + return ERR_CAST(alg); |
209 | 215 | ||
210 | /* Block size must be >= 4 bytes. */ | 216 | /* Block size must be >= 4 bytes. */ |
211 | err = -EINVAL; | 217 | err = -EINVAL; |
212 | 218 | ||
213 | Detailed description of the 'context' mode | 219 | Detailed description of the 'context' mode |
214 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 220 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
215 | 221 | ||
216 | 'context' highlights lines of interest and their context | 222 | 'context' highlights lines of interest and their context |
217 | in a diff-like style. | 223 | in a diff-like style. |
218 | 224 | ||
219 | NOTE: The diff-like output generated is NOT an applicable patch. The | 225 | NOTE: The diff-like output generated is NOT an applicable patch. The |
220 | intent of the 'context' mode is to highlight the important lines | 226 | intent of the 'context' mode is to highlight the important lines |
221 | (annotated with minus, '-') and gives some surrounding context | 227 | (annotated with minus, '-') and gives some surrounding context |
222 | lines around. This output can be used with the diff mode of | 228 | lines around. This output can be used with the diff mode of |
223 | Emacs to review the code. | 229 | Emacs to review the code. |
224 | 230 | ||
225 | Example: | 231 | Example: |
226 | 232 | ||
227 | Running | 233 | Running |
228 | make coccicheck MODE=context COCCI=scripts/coccinelle/api/err_cast.cocci | 234 | make coccicheck MODE=context COCCI=scripts/coccinelle/api/err_cast.cocci |
229 | 235 | ||
230 | will execute the following part of the SmPL script. | 236 | will execute the following part of the SmPL script. |
231 | 237 | ||
232 | <smpl> | 238 | <smpl> |
233 | @ depends on context && !patch && !org && !report@ | 239 | @ depends on context && !patch && !org && !report@ |
234 | expression x; | 240 | expression x; |
235 | @@ | 241 | @@ |
236 | 242 | ||
237 | * ERR_PTR(PTR_ERR(x)) | 243 | * ERR_PTR(PTR_ERR(x)) |
238 | </smpl> | 244 | </smpl> |
239 | 245 | ||
240 | This SmPL excerpt generates diff hunks on the standard output, as | 246 | This SmPL excerpt generates diff hunks on the standard output, as |
241 | illustrated below: | 247 | illustrated below: |
242 | 248 | ||
243 | diff -u -p /home/user/linux/crypto/ctr.c /tmp/nothing | 249 | diff -u -p /home/user/linux/crypto/ctr.c /tmp/nothing |
244 | --- /home/user/linux/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200 | 250 | --- /home/user/linux/crypto/ctr.c 2010-05-26 10:49:38.000000000 +0200 |
245 | +++ /tmp/nothing | 251 | +++ /tmp/nothing |
246 | @@ -185,7 +185,6 @@ static struct crypto_instance *crypto_ct | 252 | @@ -185,7 +185,6 @@ static struct crypto_instance *crypto_ct |
247 | alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, | 253 | alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER, |
248 | CRYPTO_ALG_TYPE_MASK); | 254 | CRYPTO_ALG_TYPE_MASK); |
249 | if (IS_ERR(alg)) | 255 | if (IS_ERR(alg)) |
250 | - return ERR_PTR(PTR_ERR(alg)); | 256 | - return ERR_PTR(PTR_ERR(alg)); |
251 | 257 | ||
252 | /* Block size must be >= 4 bytes. */ | 258 | /* Block size must be >= 4 bytes. */ |
253 | err = -EINVAL; | 259 | err = -EINVAL; |
254 | 260 | ||
255 | Detailed description of the 'org' mode | 261 | Detailed description of the 'org' mode |
256 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 262 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
257 | 263 | ||
258 | 'org' generates a report in the Org mode format of Emacs. | 264 | 'org' generates a report in the Org mode format of Emacs. |
259 | 265 | ||
260 | Example: | 266 | Example: |
261 | 267 | ||
262 | Running | 268 | Running |
263 | make coccicheck MODE=org COCCI=scripts/coccinelle/api/err_cast.cocci | 269 | make coccicheck MODE=org COCCI=scripts/coccinelle/api/err_cast.cocci |
264 | 270 | ||
265 | will execute the following part of the SmPL script. | 271 | will execute the following part of the SmPL script. |
266 | 272 | ||
267 | <smpl> | 273 | <smpl> |
268 | @r depends on !context && !patch && (org || report)@ | 274 | @r depends on !context && !patch && (org || report)@ |
269 | expression x; | 275 | expression x; |
270 | position p; | 276 | position p; |
271 | @@ | 277 | @@ |
272 | 278 | ||
273 | ERR_PTR@p(PTR_ERR(x)) | 279 | ERR_PTR@p(PTR_ERR(x)) |
274 | 280 | ||
275 | @script:python depends on org@ | 281 | @script:python depends on org@ |
276 | p << r.p; | 282 | p << r.p; |
277 | x << r.x; | 283 | x << r.x; |
278 | @@ | 284 | @@ |
279 | 285 | ||
280 | msg="ERR_CAST can be used with %s" % (x) | 286 | msg="ERR_CAST can be used with %s" % (x) |
281 | msg_safe=msg.replace("[","@(").replace("]",")") | 287 | msg_safe=msg.replace("[","@(").replace("]",")") |
282 | coccilib.org.print_todo(p[0], msg_safe) | 288 | coccilib.org.print_todo(p[0], msg_safe) |
283 | </smpl> | 289 | </smpl> |
284 | 290 | ||
285 | This SmPL excerpt generates Org entries on the standard output, as | 291 | This SmPL excerpt generates Org entries on the standard output, as |
286 | illustrated below: | 292 | illustrated below: |
287 | 293 | ||
288 | * TODO [[view:/home/user/linux/crypto/ctr.c::face=ovl-face1::linb=188::colb=9::cole=16][ERR_CAST can be used with alg]] | 294 | * TODO [[view:/home/user/linux/crypto/ctr.c::face=ovl-face1::linb=188::colb=9::cole=16][ERR_CAST can be used with alg]] |
289 | * TODO [[view:/home/user/linux/crypto/authenc.c::face=ovl-face1::linb=619::colb=9::cole=16][ERR_CAST can be used with auth]] | 295 | * TODO [[view:/home/user/linux/crypto/authenc.c::face=ovl-face1::linb=619::colb=9::cole=16][ERR_CAST can be used with auth]] |
290 | * TODO [[view:/home/user/linux/crypto/xts.c::face=ovl-face1::linb=227::colb=9::cole=16][ERR_CAST can be used with alg]] | 296 | * TODO [[view:/home/user/linux/crypto/xts.c::face=ovl-face1::linb=227::colb=9::cole=16][ERR_CAST can be used with alg]] |
291 | 297 |
scripts/coccicheck
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | SPATCH="`which ${SPATCH:=spatch}`" | 3 | SPATCH="`which ${SPATCH:=spatch}`" |
4 | 4 | ||
5 | if [ "$C" = "1" -o "$C" = "2" ]; then | 5 | if [ "$C" = "1" -o "$C" = "2" ]; then |
6 | ONLINE=1 | 6 | ONLINE=1 |
7 | 7 | ||
8 | # This requires Coccinelle >= 0.2.3 | 8 | # This requires Coccinelle >= 0.2.3 |
9 | # FLAGS="-ignore_unknown_options -very_quiet" | 9 | # FLAGS="-ignore_unknown_options -very_quiet" |
10 | # OPTIONS=$* | 10 | # OPTIONS=$* |
11 | 11 | ||
12 | # Workaround for Coccinelle < 0.2.3 | 12 | if [ "$KBUILD_EXTMOD" = "" ] ; then |
13 | FLAGS="-I $srctree/include -very_quiet" | 13 | # Workaround for Coccinelle < 0.2.3 |
14 | shift $(( $# - 1 )) | 14 | FLAGS="-I $srctree/include -very_quiet" |
15 | OPTIONS=$1 | 15 | shift $(( $# - 1 )) |
16 | OPTIONS=$1 | ||
17 | else | ||
18 | echo M= is not currently supported when C=1 or C=2 | ||
19 | exit 1 | ||
20 | fi | ||
16 | else | 21 | else |
17 | ONLINE=0 | 22 | ONLINE=0 |
18 | FLAGS="-very_quiet" | 23 | FLAGS="-very_quiet" |
19 | OPTIONS="-dir $srctree" | 24 | if [ "$KBUILD_EXTMOD" = "" ] ; then |
25 | OPTIONS="-dir $srctree" | ||
26 | else | ||
27 | OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include" | ||
28 | fi | ||
20 | fi | 29 | fi |
21 | 30 | ||
22 | if [ ! -x "$SPATCH" ]; then | 31 | if [ ! -x "$SPATCH" ]; then |
23 | echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' | 32 | echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' |
24 | exit 1 | 33 | exit 1 |
25 | fi | 34 | fi |
26 | 35 | ||
27 | if [ "$MODE" = "" ] ; then | 36 | if [ "$MODE" = "" ] ; then |
28 | if [ "$ONLINE" = "0" ] ; then | 37 | if [ "$ONLINE" = "0" ] ; then |
29 | echo 'You have not explicitly specified the mode to use. Using default "chain" mode.' | 38 | echo 'You have not explicitly specified the mode to use. Using default "chain" mode.' |
30 | echo 'All available modes will be tried (in that order): patch, report, context, org' | 39 | echo 'All available modes will be tried (in that order): patch, report, context, org' |
31 | echo 'You can specify the mode with "make coccicheck MODE=<mode>"' | 40 | echo 'You can specify the mode with "make coccicheck MODE=<mode>"' |
32 | fi | 41 | fi |
33 | MODE="chain" | 42 | MODE="chain" |
34 | elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then | 43 | elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then |
35 | FLAGS="$FLAGS -no_show_diff" | 44 | FLAGS="$FLAGS -no_show_diff" |
36 | fi | 45 | fi |
37 | 46 | ||
38 | if [ "$ONLINE" = "0" ] ; then | 47 | if [ "$ONLINE" = "0" ] ; then |
39 | echo '' | 48 | echo '' |
40 | echo 'Please check for false positives in the output before submitting a patch.' | 49 | echo 'Please check for false positives in the output before submitting a patch.' |
41 | echo 'When using "patch" mode, carefully review the patch before submitting it.' | 50 | echo 'When using "patch" mode, carefully review the patch before submitting it.' |
42 | echo '' | 51 | echo '' |
43 | fi | 52 | fi |
44 | 53 | ||
45 | coccinelle () { | 54 | coccinelle () { |
46 | COCCI="$1" | 55 | COCCI="$1" |
47 | 56 | ||
48 | OPT=`grep "Option" $COCCI | cut -d':' -f2` | 57 | OPT=`grep "Option" $COCCI | cut -d':' -f2` |
49 | 58 | ||
50 | # The option '-parse_cocci' can be used to syntactically check the SmPL files. | 59 | # The option '-parse_cocci' can be used to syntactically check the SmPL files. |
51 | # | 60 | # |
52 | # $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null | 61 | # $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null |
53 | 62 | ||
54 | if [ "$ONLINE" = "0" ] ; then | 63 | if [ "$ONLINE" = "0" ] ; then |
55 | 64 | ||
56 | FILE=`echo $COCCI | sed "s|$srctree/||"` | 65 | FILE=`echo $COCCI | sed "s|$srctree/||"` |
57 | 66 | ||
58 | echo "Processing `basename $COCCI`" | 67 | echo "Processing `basename $COCCI`" |
59 | echo "with option(s) \"$OPT\"" | 68 | echo "with option(s) \"$OPT\"" |
60 | echo '' | 69 | echo '' |
61 | echo 'Message example to submit a patch:' | 70 | echo 'Message example to submit a patch:' |
62 | 71 | ||
63 | sed -ne 's|^///||p' $COCCI | 72 | sed -ne 's|^///||p' $COCCI |
64 | 73 | ||
65 | if [ "$MODE" = "patch" ] ; then | 74 | if [ "$MODE" = "patch" ] ; then |
66 | echo ' The semantic patch that makes this change is available' | 75 | echo ' The semantic patch that makes this change is available' |
67 | elif [ "$MODE" = "report" ] ; then | 76 | elif [ "$MODE" = "report" ] ; then |
68 | echo ' The semantic patch that makes this report is available' | 77 | echo ' The semantic patch that makes this report is available' |
69 | elif [ "$MODE" = "context" ] ; then | 78 | elif [ "$MODE" = "context" ] ; then |
70 | echo ' The semantic patch that spots this code is available' | 79 | echo ' The semantic patch that spots this code is available' |
71 | elif [ "$MODE" = "org" ] ; then | 80 | elif [ "$MODE" = "org" ] ; then |
72 | echo ' The semantic patch that makes this Org report is available' | 81 | echo ' The semantic patch that makes this Org report is available' |
73 | else | 82 | else |
74 | echo ' The semantic patch that makes this output is available' | 83 | echo ' The semantic patch that makes this output is available' |
75 | fi | 84 | fi |
76 | echo " in $FILE." | 85 | echo " in $FILE." |
77 | echo '' | 86 | echo '' |
78 | echo ' More information about semantic patching is available at' | 87 | echo ' More information about semantic patching is available at' |
79 | echo ' http://coccinelle.lip6.fr/' | 88 | echo ' http://coccinelle.lip6.fr/' |
80 | echo '' | 89 | echo '' |
81 | 90 | ||
82 | if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then | 91 | if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then |
83 | echo 'Semantic patch information:' | 92 | echo 'Semantic patch information:' |
84 | sed -ne 's|^//#||p' $COCCI | 93 | sed -ne 's|^//#||p' $COCCI |
85 | echo '' | 94 | echo '' |
86 | fi | 95 | fi |
87 | fi | 96 | fi |
88 | 97 | ||
89 | if [ "$MODE" = "chain" ] ; then | 98 | if [ "$MODE" = "chain" ] ; then |
90 | $SPATCH -D patch $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ | 99 | $SPATCH -D patch $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ |
91 | $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ | 100 | $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ |
92 | $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ | 101 | $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ |
93 | $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 | 102 | $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 |
94 | else | 103 | else |
95 | $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 | 104 | $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 |
96 | fi | 105 | fi |
97 | 106 | ||
98 | } | 107 | } |
99 | 108 | ||
100 | if [ "$COCCI" = "" ] ; then | 109 | if [ "$COCCI" = "" ] ; then |
101 | for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do | 110 | for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do |
102 | coccinelle $f | 111 | coccinelle $f |
103 | done | 112 | done |
104 | else | 113 | else |
105 | coccinelle $COCCI | 114 | coccinelle $COCCI |
106 | fi | 115 | fi |
107 | 116 |
scripts/coccinelle/api/devm_request_and_ioremap.cocci
File was created | 1 | /// Reimplement a call to devm_request_mem_region followed by a call to ioremap | |
2 | /// or ioremap_nocache by a call to devm_request_and_ioremap. | ||
3 | /// Devm_request_and_ioremap was introduced in | ||
4 | /// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0. It makes the code much more | ||
5 | /// concise. | ||
6 | /// | ||
7 | /// | ||
8 | // Confidence: High | ||
9 | // Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2. | ||
10 | // Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. | ||
11 | // URL: http://coccinelle.lip6.fr/ | ||
12 | // Comments: | ||
13 | // Options: -no_includes -include_headers | ||
14 | |||
15 | virtual patch | ||
16 | virtual org | ||
17 | virtual report | ||
18 | virtual context | ||
19 | |||
20 | @nm@ | ||
21 | expression myname; | ||
22 | identifier i; | ||
23 | @@ | ||
24 | |||
25 | struct platform_driver i = { .driver = { .name = myname } }; | ||
26 | |||
27 | @depends on patch@ | ||
28 | expression dev,res,size; | ||
29 | @@ | ||
30 | |||
31 | -if (!devm_request_mem_region(dev, res->start, size, | ||
32 | - \(res->name\|dev_name(dev)\))) { | ||
33 | - ... | ||
34 | - return ...; | ||
35 | -} | ||
36 | ... when != res->start | ||
37 | ( | ||
38 | -devm_ioremap(dev,res->start,size) | ||
39 | +devm_request_and_ioremap(dev,res) | ||
40 | | | ||
41 | -devm_ioremap_nocache(dev,res->start,size) | ||
42 | +devm_request_and_ioremap(dev,res) | ||
43 | ) | ||
44 | ... when any | ||
45 | when != res->start | ||
46 | |||
47 | // this rule is separate from the previous one, because a single file can | ||
48 | // have multiple values of myname | ||
49 | @depends on patch@ | ||
50 | expression dev,res,size; | ||
51 | expression nm.myname; | ||
52 | @@ | ||
53 | |||
54 | -if (!devm_request_mem_region(dev, res->start, size,myname)) { | ||
55 | - ... | ||
56 | - return ...; | ||
57 | -} | ||
58 | ... when != res->start | ||
59 | ( | ||
60 | -devm_ioremap(dev,res->start,size) | ||
61 | +devm_request_and_ioremap(dev,res) | ||
62 | | | ||
63 | -devm_ioremap_nocache(dev,res->start,size) | ||
64 | +devm_request_and_ioremap(dev,res) | ||
65 | ) | ||
66 | ... when any | ||
67 | when != res->start | ||
68 | |||
69 | |||
70 | @pb depends on org || report || context@ | ||
71 | expression dev,res,size; | ||
72 | expression nm.myname; | ||
73 | position p1,p2; | ||
74 | @@ | ||
75 | |||
76 | *if | ||
77 | (!devm_request_mem_region@p1(dev, res->start, size, | ||
78 | \(res->name\|dev_name(dev)\|myname\))) { | ||
79 | ... | ||
80 | return ...; | ||
81 | } | ||
82 | ... when != res->start | ||
83 | ( | ||
84 | *devm_ioremap@p2(dev,res->start,size) | ||
85 | | | ||
86 | *devm_ioremap_nocache@p2(dev,res->start,size) | ||
87 | ) | ||
88 | ... when any | ||
89 | when != res->start | ||
90 | |||
91 | @script:python depends on org@ | ||
92 | p1 << pb.p1; | ||
93 | p2 << pb.p2; | ||
94 | @@ | ||
95 | |||
96 | cocci.print_main("INFO: replace by devm_request_and_ioremap",p1) | ||
97 | cocci.print_secs("",p2) | ||
98 | |||
99 | @script:python depends on report@ | ||
100 | p1 << pb.p1; | ||
101 | p2 << pb.p2; | ||
102 | @@ | ||
103 | |||
104 | msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line) | ||
105 | coccilib.report.print_report(p1[0],msg) | ||
106 |
scripts/coccinelle/api/kstrdup.cocci
1 | /// Use kstrdup rather than duplicating its implementation | 1 | /// Use kstrdup rather than duplicating its implementation |
2 | /// | 2 | /// |
3 | // Confidence: High | 3 | // Confidence: High |
4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 4 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 6 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
7 | // URL: http://coccinelle.lip6.fr/ | 7 | // URL: http://coccinelle.lip6.fr/ |
8 | // Comments: | 8 | // Comments: |
9 | // Options: -no_includes -include_headers | 9 | // Options: -no_includes -include_headers |
10 | 10 | ||
11 | virtual patch | 11 | virtual patch |
12 | virtual context | ||
13 | virtual org | ||
14 | virtual report | ||
12 | 15 | ||
13 | @@ | 16 | @depends on patch@ |
14 | expression from,to; | 17 | expression from,to; |
15 | expression flag,E1,E2; | 18 | expression flag,E1,E2; |
16 | statement S; | 19 | statement S; |
17 | @@ | 20 | @@ |
18 | 21 | ||
19 | - to = kmalloc(strlen(from) + 1,flag); | 22 | - to = kmalloc(strlen(from) + 1,flag); |
20 | + to = kstrdup(from, flag); | 23 | + to = kstrdup(from, flag); |
21 | ... when != \(from = E1 \| to = E1 \) | 24 | ... when != \(from = E1 \| to = E1 \) |
22 | if (to==NULL || ...) S | 25 | if (to==NULL || ...) S |
23 | ... when != \(from = E2 \| to = E2 \) | 26 | ... when != \(from = E2 \| to = E2 \) |
24 | - strcpy(to, from); | 27 | - strcpy(to, from); |
25 | 28 | ||
26 | @@ | 29 | @depends on patch@ |
27 | expression x,from,to; | 30 | expression x,from,to; |
28 | expression flag,E1,E2,E3; | 31 | expression flag,E1,E2,E3; |
29 | statement S; | 32 | statement S; |
30 | @@ | 33 | @@ |
31 | 34 | ||
32 | - x = strlen(from) + 1; | 35 | - x = strlen(from) + 1; |
33 | ... when != \( x = E1 \| from = E1 \) | 36 | ... when != \( x = E1 \| from = E1 \) |
34 | - to = \(kmalloc\|kzalloc\)(x,flag); | 37 | - to = \(kmalloc\|kzalloc\)(x,flag); |
35 | + to = kstrdup(from, flag); | 38 | + to = kstrdup(from, flag); |
36 | ... when != \(x = E2 \| from = E2 \| to = E2 \) | 39 | ... when != \(x = E2 \| from = E2 \| to = E2 \) |
37 | if (to==NULL || ...) S | 40 | if (to==NULL || ...) S |
38 | ... when != \(x = E3 \| from = E3 \| to = E3 \) | 41 | ... when != \(x = E3 \| from = E3 \| to = E3 \) |
39 | - memcpy(to, from, x); | 42 | - memcpy(to, from, x); |
43 | |||
44 | // --------------------------------------------------------------------- | ||
45 | |||
46 | @r1 depends on !patch exists@ | ||
47 | expression from,to; | ||
48 | expression flag,E1,E2; | ||
49 | statement S; | ||
50 | position p1,p2; | ||
51 | @@ | ||
52 | |||
53 | * to = kmalloc@p1(strlen(from) + 1,flag); | ||
54 | ... when != \(from = E1 \| to = E1 \) | ||
55 | if (to==NULL || ...) S | ||
56 | ... when != \(from = E2 \| to = E2 \) | ||
57 | * strcpy@p2(to, from); | ||
58 | |||
59 | @r2 depends on !patch exists@ | ||
60 | expression x,from,to; | ||
61 | expression flag,E1,E2,E3; | ||
62 | statement S; | ||
63 | position p1,p2; | ||
64 | @@ | ||
65 | |||
66 | * x = strlen(from) + 1; | ||
67 | ... when != \( x = E1 \| from = E1 \) | ||
68 | * to = \(kmalloc@p1\|kzalloc@p2\)(x,flag); | ||
69 | ... when != \(x = E2 \| from = E2 \| to = E2 \) | ||
70 | if (to==NULL || ...) S | ||
71 | ... when != \(x = E3 \| from = E3 \| to = E3 \) | ||
72 | * memcpy@p2(to, from, x); | ||
73 | |||
74 | @script:python depends on org@ | ||
75 | p1 << r1.p1; | ||
76 | p2 << r1.p2; | ||
77 | @@ | ||
78 | |||
79 | cocci.print_main("WARNING opportunity for kstrdep",p1) | ||
80 | cocci.print_secs("strcpy",p2) | ||
81 | |||
82 | @script:python depends on org@ | ||
83 | p1 << r2.p1; | ||
84 | p2 << r2.p2; | ||
85 | @@ | ||
86 | |||
87 | cocci.print_main("WARNING opportunity for kstrdep",p1) | ||
88 | cocci.print_secs("memcpy",p2) | ||
89 | |||
90 | @script:python depends on report@ | ||
91 | p1 << r1.p1; | ||
92 | p2 << r1.p2; | ||
93 | @@ | ||
94 | |||
95 | msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line) | ||
96 | coccilib.report.print_report(p1[0], msg) | ||
97 | |||
98 | @script:python depends on report@ | ||
99 | p1 << r2.p1; | ||
100 | p2 << r2.p2; | ||
101 | @@ | ||
102 | |||
103 | msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line) | ||
104 | coccilib.report.print_report(p1[0], msg) | ||
40 | 105 |
scripts/coccinelle/api/memdup.cocci
1 | /// Use kmemdup rather than duplicating its implementation | 1 | /// Use kmemdup rather than duplicating its implementation |
2 | /// | 2 | /// |
3 | // Confidence: High | 3 | // Confidence: High |
4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 4 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 6 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
7 | // URL: http://coccinelle.lip6.fr/ | 7 | // URL: http://coccinelle.lip6.fr/ |
8 | // Comments: | 8 | // Comments: |
9 | // Options: -no_includes -include_headers | 9 | // Options: -no_includes -include_headers |
10 | 10 | ||
11 | virtual patch | 11 | virtual patch |
12 | virtual context | ||
13 | virtual org | ||
14 | virtual report | ||
12 | 15 | ||
13 | @r1@ | 16 | @r1@ |
14 | expression from,to; | 17 | expression from,to; |
15 | expression flag; | 18 | expression flag; |
16 | position p; | 19 | position p; |
17 | @@ | 20 | @@ |
18 | 21 | ||
19 | to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag); | 22 | to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag); |
20 | 23 | ||
21 | @r2@ | 24 | @r2@ |
22 | expression x,from,to; | 25 | expression x,from,to; |
23 | expression flag,E1; | 26 | expression flag,E1; |
24 | position p; | 27 | position p; |
25 | @@ | 28 | @@ |
26 | 29 | ||
27 | x = strlen(from) + 1; | 30 | x = strlen(from) + 1; |
28 | ... when != \( x = E1 \| from = E1 \) | 31 | ... when != \( x = E1 \| from = E1 \) |
29 | to = \(kmalloc@p\|kzalloc@p\)(x,flag); | 32 | to = \(kmalloc@p\|kzalloc@p\)(x,flag); |
30 | 33 | ||
31 | @@ | 34 | @depends on patch@ |
32 | expression from,to,size,flag; | 35 | expression from,to,size,flag; |
33 | position p != {r1.p,r2.p}; | 36 | position p != {r1.p,r2.p}; |
34 | statement S; | 37 | statement S; |
35 | @@ | 38 | @@ |
36 | 39 | ||
37 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); | 40 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); |
38 | + to = kmemdup(from,size,flag); | 41 | + to = kmemdup(from,size,flag); |
39 | if (to==NULL || ...) S | 42 | if (to==NULL || ...) S |
40 | - memcpy(to, from, size); | 43 | - memcpy(to, from, size); |
44 | |||
45 | @r depends on !patch@ | ||
46 | expression from,to,size,flag; | ||
47 | position p != {r1.p,r2.p}; | ||
48 | statement S; | ||
49 | @@ | ||
50 | |||
51 | * to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
52 | to = kmemdup(from,size,flag); | ||
53 | if (to==NULL || ...) S | ||
54 | * memcpy(to, from, size); | ||
55 | |||
56 | @script:python depends on org@ | ||
57 | p << r.p; | ||
58 | @@ | ||
59 | |||
60 | coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep") | ||
61 | |||
62 | @script:python depends on report@ | ||
63 | p << r.p; | ||
64 | @@ | ||
65 | |||
66 | coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep") | ||
41 | 67 |
scripts/coccinelle/api/memdup_user.cocci
1 | /// Use kmemdup_user rather than duplicating its implementation | 1 | /// Use memdup_user rather than duplicating its implementation |
2 | /// This is a little bit restricted to reduce false positives | 2 | /// This is a little bit restricted to reduce false positives |
3 | /// | 3 | /// |
4 | // Confidence: High | 4 | // Confidence: High |
5 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
6 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 6 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
7 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 7 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
8 | // URL: http://coccinelle.lip6.fr/ | 8 | // URL: http://coccinelle.lip6.fr/ |
9 | // Comments: | 9 | // Comments: |
10 | // Options: -no_includes -include_headers | 10 | // Options: -no_includes -include_headers |
11 | 11 | ||
12 | virtual patch | 12 | virtual patch |
13 | virtual context | ||
14 | virtual org | ||
15 | virtual report | ||
13 | 16 | ||
14 | @@ | 17 | @depends on patch@ |
15 | expression from,to,size,flag; | 18 | expression from,to,size,flag; |
16 | position p; | ||
17 | identifier l1,l2; | 19 | identifier l1,l2; |
18 | @@ | 20 | @@ |
19 | 21 | ||
20 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); | 22 | - to = \(kmalloc\|kzalloc\)(size,flag); |
21 | + to = memdup_user(from,size); | 23 | + to = memdup_user(from,size); |
22 | if ( | 24 | if ( |
23 | - to==NULL | 25 | - to==NULL |
24 | + IS_ERR(to) | 26 | + IS_ERR(to) |
25 | || ...) { | 27 | || ...) { |
26 | <+... when != goto l1; | 28 | <+... when != goto l1; |
27 | - -ENOMEM | 29 | - -ENOMEM |
28 | + PTR_ERR(to) | 30 | + PTR_ERR(to) |
29 | ...+> | 31 | ...+> |
30 | } | 32 | } |
31 | - if (copy_from_user(to, from, size) != 0) { | 33 | - if (copy_from_user(to, from, size) != 0) { |
32 | - <+... when != goto l2; | 34 | - <+... when != goto l2; |
33 | - -EFAULT | 35 | - -EFAULT |
34 | - ...+> | 36 | - ...+> |
35 | - } | 37 | - } |
38 | |||
39 | @r depends on !patch@ | ||
40 | expression from,to,size,flag; | ||
41 | position p; | ||
42 | statement S1,S2; | ||
43 | @@ | ||
44 | |||
45 | * to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
46 | if (to==NULL || ...) S1 | ||
47 | if (copy_from_user(to, from, size) != 0) | ||
48 | S2 | ||
49 | |||
50 | @script:python depends on org@ | ||
51 | p << r.p; | ||
52 | @@ | ||
53 | |||
54 | coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user") | ||
55 | |||
56 | @script:python depends on report@ | ||
57 | p << r.p; | ||
58 | @@ | ||
59 | |||
60 | coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user") |
scripts/coccinelle/free/devm_free.cocci
File was created | 1 | /// Find uses of standard freeing functons on values allocated using devm_ | |
2 | /// functions. Values allocated using the devm_functions are freed when | ||
3 | /// the device is detached, and thus the use of the standard freeing | ||
4 | /// function would cause a double free. | ||
5 | /// See Documentation/driver-model/devres.txt for more information. | ||
6 | /// | ||
7 | /// A difficulty of detecting this problem is that the standard freeing | ||
8 | /// function might be called from a different function than the one | ||
9 | /// containing the allocation function. It is thus necessary to make the | ||
10 | /// connection between the allocation function and the freeing function. | ||
11 | /// Here this is done using the specific argument text, which is prone to | ||
12 | /// false positives. There is no rule for the request_region and | ||
13 | /// request_mem_region variants because this heuristic seems to be a bit | ||
14 | /// less reliable in these cases. | ||
15 | /// | ||
16 | // Confidence: Moderate | ||
17 | // Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2. | ||
18 | // Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. | ||
19 | // URL: http://coccinelle.lip6.fr/ | ||
20 | // Comments: | ||
21 | // Options: -no_includes -include_headers | ||
22 | |||
23 | virtual org | ||
24 | virtual report | ||
25 | virtual context | ||
26 | |||
27 | @r depends on context || org || report@ | ||
28 | expression x; | ||
29 | @@ | ||
30 | |||
31 | ( | ||
32 | x = devm_kzalloc(...) | ||
33 | | | ||
34 | x = devm_request_irq(...) | ||
35 | | | ||
36 | x = devm_ioremap(...) | ||
37 | | | ||
38 | x = devm_ioremap_nocache(...) | ||
39 | | | ||
40 | x = devm_ioport_map(...) | ||
41 | ) | ||
42 | |||
43 | @pb@ | ||
44 | expression r.x; | ||
45 | position p; | ||
46 | @@ | ||
47 | |||
48 | ( | ||
49 | * kfree@p(x) | ||
50 | | | ||
51 | * free_irq@p(x) | ||
52 | | | ||
53 | * iounmap@p(x) | ||
54 | | | ||
55 | * ioport_unmap@p(x) | ||
56 | ) | ||
57 | |||
58 | @script:python depends on org@ | ||
59 | p << pb.p; | ||
60 | @@ | ||
61 | |||
62 | msg="WARNING: invalid free of devm_ allocated data" | ||
63 | coccilib.org.print_todo(p[0], msg) | ||
64 | |||
65 | @script:python depends on report@ | ||
66 | p << pb.p; | ||
67 | @@ | ||
68 | |||
69 | msg="WARNING: invalid free of devm_ allocated data" | ||
70 | coccilib.report.print_report(p[0], msg) | ||
71 | |||
72 |
scripts/coccinelle/free/kfree.cocci
1 | /// Find a use after free. | 1 | /// Find a use after free. |
2 | //# Values of variables may imply that some | 2 | //# Values of variables may imply that some |
3 | //# execution paths are not possible, resulting in false positives. | 3 | //# execution paths are not possible, resulting in false positives. |
4 | //# Another source of false positives are macros such as | 4 | //# Another source of false positives are macros such as |
5 | //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument | 5 | //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument |
6 | /// | 6 | /// |
7 | // Confidence: Moderate | 7 | // Confidence: Moderate |
8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 8 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 9 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 10 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
11 | // URL: http://coccinelle.lip6.fr/ | 11 | // URL: http://coccinelle.lip6.fr/ |
12 | // Comments: | 12 | // Comments: |
13 | // Options: -no_includes -include_headers | 13 | // Options: -no_includes -include_headers |
14 | 14 | ||
15 | virtual org | 15 | virtual org |
16 | virtual report | 16 | virtual report |
17 | 17 | ||
18 | @free@ | 18 | @free@ |
19 | expression E; | 19 | expression E; |
20 | position p1; | 20 | position p1; |
21 | @@ | 21 | @@ |
22 | 22 | ||
23 | kfree@p1(E) | 23 | kfree@p1(E) |
24 | 24 | ||
25 | @print expression@ | 25 | @print expression@ |
26 | constant char *c; | 26 | constant char [] c; |
27 | expression free.E,E2; | 27 | expression free.E,E2; |
28 | type T; | 28 | type T; |
29 | position p; | 29 | position p; |
30 | identifier f; | 30 | identifier f; |
31 | @@ | 31 | @@ |
32 | 32 | ||
33 | ( | 33 | ( |
34 | f(...,c,...,(T)E@p,...) | 34 | f(...,c,...,(T)E@p,...) |
35 | | | 35 | | |
36 | E@p == E2 | 36 | E@p == E2 |
37 | | | 37 | | |
38 | E@p != E2 | 38 | E@p != E2 |
39 | | | 39 | | |
40 | E2 == E@p | ||
41 | | | ||
42 | E2 != E@p | ||
43 | | | ||
40 | !E@p | 44 | !E@p |
41 | | | 45 | | |
42 | E@p || ... | 46 | E@p || ... |
43 | ) | 47 | ) |
44 | 48 | ||
45 | @sz@ | 49 | @sz@ |
46 | expression free.E; | 50 | expression free.E; |
47 | position p; | 51 | position p; |
48 | @@ | 52 | @@ |
49 | 53 | ||
50 | sizeof(<+...E@p...+>) | 54 | sizeof(<+...E@p...+>) |
51 | 55 | ||
52 | @loop exists@ | 56 | @loop exists@ |
53 | expression E; | 57 | expression E; |
54 | identifier l; | 58 | identifier l; |
55 | position ok; | 59 | position ok; |
56 | @@ | 60 | @@ |
57 | 61 | ||
58 | while (1) { ... | 62 | while (1) { ... |
59 | kfree@ok(E) | 63 | kfree@ok(E) |
60 | ... when != break; | 64 | ... when != break; |
61 | when != goto l; | 65 | when != goto l; |
62 | when forall | 66 | when forall |
63 | } | 67 | } |
64 | 68 | ||
65 | @r exists@ | 69 | @r exists@ |
66 | expression free.E, subE<=free.E, E2; | 70 | expression free.E, subE<=free.E, E2; |
67 | expression E1; | 71 | expression E1; |
68 | iterator iter; | 72 | iterator iter; |
69 | statement S; | 73 | statement S; |
70 | position free.p1!=loop.ok,p2!={print.p,sz.p}; | 74 | position free.p1!=loop.ok,p2!={print.p,sz.p}; |
71 | @@ | 75 | @@ |
72 | 76 | ||
73 | kfree@p1(E,...) | 77 | kfree@p1(E,...) |
74 | ... | 78 | ... |
75 | ( | 79 | ( |
76 | iter(...,subE,...) S // no use | 80 | iter(...,subE,...) S // no use |
77 | | | 81 | | |
78 | list_remove_head(E1,subE,...) | 82 | list_remove_head(E1,subE,...) |
79 | | | 83 | | |
80 | subE = E2 | 84 | subE = E2 |
81 | | | 85 | | |
82 | subE++ | 86 | subE++ |
83 | | | 87 | | |
84 | ++subE | 88 | ++subE |
85 | | | 89 | | |
86 | --subE | 90 | --subE |
87 | | | 91 | | |
88 | subE-- | 92 | subE-- |
89 | | | 93 | | |
90 | &subE | 94 | &subE |
91 | | | 95 | | |
92 | BUG(...) | 96 | BUG(...) |
93 | | | 97 | | |
94 | BUG_ON(...) | 98 | BUG_ON(...) |
95 | | | 99 | | |
96 | return_VALUE(...) | 100 | return_VALUE(...) |
97 | | | 101 | | |
98 | return_ACPI_STATUS(...) | 102 | return_ACPI_STATUS(...) |
99 | | | 103 | | |
100 | E@p2 // bad use | 104 | E@p2 // bad use |
101 | ) | 105 | ) |
102 | 106 | ||
103 | @script:python depends on org@ | 107 | @script:python depends on org@ |
104 | p1 << free.p1; | 108 | p1 << free.p1; |
105 | p2 << r.p2; | 109 | p2 << r.p2; |
106 | @@ | 110 | @@ |
107 | 111 | ||
108 | cocci.print_main("kfree",p1) | 112 | cocci.print_main("kfree",p1) |
109 | cocci.print_secs("ref",p2) | 113 | cocci.print_secs("ref",p2) |
110 | 114 | ||
111 | @script:python depends on report@ | 115 | @script:python depends on report@ |
112 | p1 << free.p1; | 116 | p1 << free.p1; |
113 | p2 << r.p2; | 117 | p2 << r.p2; |
114 | @@ | 118 | @@ |
115 | 119 | ||
116 | msg = "reference preceded by free on line %s" % (p1[0].line) | 120 | msg = "ERROR: reference preceded by free on line %s" % (p1[0].line) |
117 | coccilib.report.print_report(p2[0],msg) | 121 | coccilib.report.print_report(p2[0],msg) |
118 | 122 |
scripts/coccinelle/iterators/fen.cocci
1 | /// These iterators only exit normally when the loop cursor is NULL, so there | 1 | /// These iterators only exit normally when the loop cursor is NULL, so there |
2 | /// is no point to call of_node_put on the final value. | 2 | /// is no point to call of_node_put on the final value. |
3 | /// | 3 | /// |
4 | // Confidence: High | 4 | // Confidence: High |
5 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
6 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 6 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
7 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 7 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
8 | // URL: http://coccinelle.lip6.fr/ | 8 | // URL: http://coccinelle.lip6.fr/ |
9 | // Comments: | 9 | // Comments: |
10 | // Options: -no_includes -include_headers | 10 | // Options: -no_includes -include_headers |
11 | 11 | ||
12 | virtual patch | 12 | virtual patch |
13 | virtual context | ||
14 | virtual org | ||
15 | virtual report | ||
13 | 16 | ||
14 | @@ | 17 | @depends on patch@ |
15 | iterator name for_each_node_by_name; | 18 | iterator name for_each_node_by_name; |
16 | expression np,E; | 19 | expression np,E; |
17 | identifier l; | 20 | identifier l; |
18 | @@ | 21 | @@ |
19 | 22 | ||
20 | for_each_node_by_name(np,...) { | 23 | for_each_node_by_name(np,...) { |
21 | ... when != break; | 24 | ... when != break; |
22 | when != goto l; | 25 | when != goto l; |
23 | } | 26 | } |
24 | ... when != np = E | 27 | ... when != np = E |
25 | - of_node_put(np); | 28 | - of_node_put(np); |
26 | 29 | ||
27 | @@ | 30 | @depends on patch@ |
28 | iterator name for_each_node_by_type; | 31 | iterator name for_each_node_by_type; |
29 | expression np,E; | 32 | expression np,E; |
30 | identifier l; | 33 | identifier l; |
31 | @@ | 34 | @@ |
32 | 35 | ||
33 | for_each_node_by_type(np,...) { | 36 | for_each_node_by_type(np,...) { |
34 | ... when != break; | 37 | ... when != break; |
35 | when != goto l; | 38 | when != goto l; |
36 | } | 39 | } |
37 | ... when != np = E | 40 | ... when != np = E |
38 | - of_node_put(np); | 41 | - of_node_put(np); |
39 | 42 | ||
40 | @@ | 43 | @depends on patch@ |
41 | iterator name for_each_compatible_node; | 44 | iterator name for_each_compatible_node; |
42 | expression np,E; | 45 | expression np,E; |
43 | identifier l; | 46 | identifier l; |
44 | @@ | 47 | @@ |
45 | 48 | ||
46 | for_each_compatible_node(np,...) { | 49 | for_each_compatible_node(np,...) { |
47 | ... when != break; | 50 | ... when != break; |
48 | when != goto l; | 51 | when != goto l; |
49 | } | 52 | } |
50 | ... when != np = E | 53 | ... when != np = E |
51 | - of_node_put(np); | 54 | - of_node_put(np); |
52 | 55 | ||
53 | @@ | 56 | @depends on patch@ |
54 | iterator name for_each_matching_node; | 57 | iterator name for_each_matching_node; |
55 | expression np,E; | 58 | expression np,E; |
56 | identifier l; | 59 | identifier l; |
57 | @@ | 60 | @@ |
58 | 61 | ||
59 | for_each_matching_node(np,...) { | 62 | for_each_matching_node(np,...) { |
60 | ... when != break; | 63 | ... when != break; |
61 | when != goto l; | 64 | when != goto l; |
62 | } | 65 | } |
63 | ... when != np = E | 66 | ... when != np = E |
64 | - of_node_put(np); | 67 | - of_node_put(np); |
68 | |||
69 | // ---------------------------------------------------------------------- | ||
70 | |||
71 | @r depends on !patch forall@ | ||
72 | //iterator name for_each_node_by_name; | ||
73 | //iterator name for_each_node_by_type; | ||
74 | //iterator name for_each_compatible_node; | ||
75 | //iterator name for_each_matching_node; | ||
76 | expression np,E; | ||
77 | identifier l; | ||
78 | position p1,p2; | ||
79 | @@ | ||
80 | |||
81 | ( | ||
82 | *for_each_node_by_name@p1(np,...) | ||
83 | { | ||
84 | ... when != break; | ||
85 | when != goto l; | ||
86 | } | ||
87 | | | ||
88 | *for_each_node_by_type@p1(np,...) | ||
89 | { | ||
90 | ... when != break; | ||
91 | when != goto l; | ||
92 | } | ||
93 | | | ||
94 | *for_each_compatible_node@p1(np,...) | ||
95 | { | ||
96 | ... when != break; | ||
97 | when != goto l; | ||
98 | } | ||
99 | | | ||
100 | *for_each_matching_node@p1(np,...) | ||
101 | { | ||
102 | ... when != break; | ||
103 | when != goto l; | ||
104 | } | ||
105 | ) | ||
106 | ... when != np = E | ||
107 | * of_node_put@p2(np); | ||
108 | |||
109 | @script:python depends on org@ | ||
110 | p1 << r.p1; | ||
111 | p2 << r.p2; | ||
112 | @@ | ||
113 | |||
114 | cocci.print_main("unneeded of_node_put",p2) | ||
115 | cocci.print_secs("iterator",p1) | ||
116 | |||
117 | @script:python depends on report@ | ||
118 | p1 << r.p1; | ||
119 | p2 << r.p2; | ||
120 | @@ | ||
121 | |||
122 | msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line) | ||
123 | coccilib.report.print_report(p2[0], msg) | ||
65 | 124 |
scripts/coccinelle/iterators/itnull.cocci
1 | /// Many iterators have the property that the first argument is always bound | 1 | /// Many iterators have the property that the first argument is always bound |
2 | /// to a real list element, never NULL. False positives arise for some | 2 | /// to a real list element, never NULL. |
3 | /// iterators that do not have this property, or in cases when the loop | 3 | //# False positives arise for some iterators that do not have this property, |
4 | /// cursor is reassigned. The latter should only happen when the matched | 4 | //# or in cases when the loop cursor is reassigned. The latter should only |
5 | /// code is on the way to a loop exit (break, goto, or return). | 5 | //# happen when the matched code is on the way to a loop exit (break, goto, |
6 | //# or return). | ||
6 | /// | 7 | /// |
7 | // Confidence: Moderate | 8 | // Confidence: Moderate |
8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 9 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 10 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 11 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
11 | // URL: http://coccinelle.lip6.fr/ | 12 | // URL: http://coccinelle.lip6.fr/ |
12 | // Comments: | 13 | // Comments: |
13 | // Options: -no_includes -include_headers | 14 | // Options: -no_includes -include_headers |
14 | 15 | ||
15 | virtual patch | 16 | virtual patch |
17 | virtual context | ||
18 | virtual org | ||
19 | virtual report | ||
16 | 20 | ||
17 | @@ | 21 | @depends on patch@ |
18 | iterator I; | 22 | iterator I; |
19 | expression x,E,E1,E2; | 23 | expression x,E,E1,E2; |
20 | statement S,S1,S2; | 24 | statement S,S1,S2; |
21 | @@ | 25 | @@ |
22 | 26 | ||
23 | I(x,...) { <... | 27 | I(x,...) { <... |
24 | ( | 28 | ( |
25 | - if (x == NULL && ...) S | 29 | - if (x == NULL && ...) S |
26 | | | 30 | | |
27 | - if (x != NULL || ...) | 31 | - if (x != NULL || ...) |
28 | S | 32 | S |
29 | | | 33 | | |
30 | - (x == NULL) || | 34 | - (x == NULL) || |
31 | E | 35 | E |
32 | | | 36 | | |
33 | - (x != NULL) && | 37 | - (x != NULL) && |
34 | E | 38 | E |
35 | | | 39 | | |
36 | - (x == NULL && ...) ? E1 : | 40 | - (x == NULL && ...) ? E1 : |
37 | E2 | 41 | E2 |
38 | | | 42 | | |
39 | - (x != NULL || ...) ? | 43 | - (x != NULL || ...) ? |
40 | E1 | 44 | E1 |
41 | - : E2 | 45 | - : E2 |
42 | | | 46 | | |
43 | - if (x == NULL && ...) S1 else | 47 | - if (x == NULL && ...) S1 else |
44 | S2 | 48 | S2 |
45 | | | 49 | | |
46 | - if (x != NULL || ...) | 50 | - if (x != NULL || ...) |
47 | S1 | 51 | S1 |
48 | - else S2 | 52 | - else S2 |
49 | | | 53 | | |
50 | + BAD( | 54 | + BAD( |
51 | x == NULL | 55 | x == NULL |
52 | + ) | 56 | + ) |
53 | | | 57 | | |
54 | + BAD( | 58 | + BAD( |
55 | x != NULL | 59 | x != NULL |
56 | + ) | 60 | + ) |
57 | ) | 61 | ) |
58 | ...> } | 62 | ...> } |
63 | |||
64 | @r depends on !patch exists@ | ||
65 | iterator I; | ||
66 | expression x,E; | ||
67 | position p1,p2; | ||
68 | @@ | ||
69 | |||
70 | *I@p1(x,...) | ||
71 | { ... when != x = E | ||
72 | ( | ||
73 | * x@p2 == NULL | ||
74 | | | ||
75 | * x@p2 != NULL | ||
76 | ) | ||
77 | ... when any | ||
78 | } | ||
79 | |||
80 | @script:python depends on org@ | ||
81 | p1 << r.p1; | ||
82 | p2 << r.p2; | ||
83 | @@ | ||
84 | |||
85 | cocci.print_main("iterator-bound variable",p1) | ||
86 | cocci.print_secs("useless NULL test",p2) | ||
87 | |||
88 | @script:python depends on report@ | ||
89 | p1 << r.p1; | ||
90 | p2 << r.p2; | ||
91 | @@ | ||
92 | |||
93 | msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line) | ||
94 | coccilib.report.print_report(p2[0], msg) | ||
95 |
scripts/coccinelle/locks/call_kern.cocci
1 | /// Find functions that refer to GFP_KERNEL but are called with locks held. | 1 | /// Find functions that refer to GFP_KERNEL but are called with locks held. |
2 | /// The proposed change of converting the GFP_KERNEL is not necessarily the | 2 | //# The proposed change of converting the GFP_KERNEL is not necessarily the |
3 | /// correct one. It may be desired to unlock the lock, or to not call the | 3 | //# correct one. It may be desired to unlock the lock, or to not call the |
4 | /// function under the lock in the first place. | 4 | //# function under the lock in the first place. |
5 | /// | 5 | /// |
6 | // Confidence: Moderate | 6 | // Confidence: Moderate |
7 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 7 | // Copyright: (C) 2012 Nicolas Palix. GPLv2. |
8 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 8 | // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. |
9 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 9 | // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. |
10 | // URL: http://coccinelle.lip6.fr/ | 10 | // URL: http://coccinelle.lip6.fr/ |
11 | // Comments: | 11 | // Comments: |
12 | // Options: -no_includes -include_headers | 12 | // Options: -no_includes -include_headers |
13 | 13 | ||
14 | virtual patch | 14 | virtual patch |
15 | virtual context | ||
16 | virtual org | ||
17 | virtual report | ||
15 | 18 | ||
16 | @gfp exists@ | 19 | @gfp exists@ |
17 | identifier fn; | 20 | identifier fn; |
18 | position p; | 21 | position p; |
19 | @@ | 22 | @@ |
20 | 23 | ||
21 | fn(...) { | 24 | fn(...) { |
22 | ... when != read_unlock_irq(...) | 25 | ... when != read_unlock_irq(...) |
23 | when != write_unlock_irq(...) | 26 | when != write_unlock_irq(...) |
24 | when != read_unlock_irqrestore(...) | 27 | when != read_unlock_irqrestore(...) |
25 | when != write_unlock_irqrestore(...) | 28 | when != write_unlock_irqrestore(...) |
26 | when != spin_unlock(...) | 29 | when != spin_unlock(...) |
27 | when != spin_unlock_irq(...) | 30 | when != spin_unlock_irq(...) |
28 | when != spin_unlock_irqrestore(...) | 31 | when != spin_unlock_irqrestore(...) |
29 | when != local_irq_enable(...) | 32 | when != local_irq_enable(...) |
30 | when any | 33 | when any |
31 | GFP_KERNEL@p | 34 | GFP_KERNEL@p |
32 | ... when any | 35 | ... when any |
33 | } | 36 | } |
34 | 37 | ||
35 | @locked@ | 38 | @locked exists@ |
36 | identifier gfp.fn; | 39 | identifier gfp.fn; |
40 | position p1,p2; | ||
37 | @@ | 41 | @@ |
38 | 42 | ||
39 | ( | 43 | ( |
40 | read_lock_irq | 44 | read_lock_irq@p1 |
41 | | | 45 | | |
42 | write_lock_irq | 46 | write_lock_irq@p1 |
43 | | | 47 | | |
44 | read_lock_irqsave | 48 | read_lock_irqsave@p1 |
45 | | | 49 | | |
46 | write_lock_irqsave | 50 | write_lock_irqsave@p1 |
47 | | | 51 | | |
48 | spin_lock | 52 | spin_lock@p1 |
49 | | | 53 | | |
50 | spin_trylock | 54 | spin_trylock@p1 |
51 | | | 55 | | |
52 | spin_lock_irq | 56 | spin_lock_irq@p1 |
53 | | | 57 | | |
54 | spin_lock_irqsave | 58 | spin_lock_irqsave@p1 |
55 | | | 59 | | |
56 | local_irq_disable | 60 | local_irq_disable@p1 |
57 | ) | 61 | ) |
58 | (...) | 62 | (...) |
59 | ... when != read_unlock_irq(...) | 63 | ... when != read_unlock_irq(...) |
60 | when != write_unlock_irq(...) | 64 | when != write_unlock_irq(...) |
61 | when != read_unlock_irqrestore(...) | 65 | when != read_unlock_irqrestore(...) |
62 | when != write_unlock_irqrestore(...) | 66 | when != write_unlock_irqrestore(...) |
63 | when != spin_unlock(...) | 67 | when != spin_unlock(...) |
64 | when != spin_unlock_irq(...) | 68 | when != spin_unlock_irq(...) |
65 | when != spin_unlock_irqrestore(...) | 69 | when != spin_unlock_irqrestore(...) |
66 | when != local_irq_enable(...) | 70 | when != local_irq_enable(...) |
67 | fn(...) | 71 | fn@p2(...) |
68 | 72 | ||
69 | @depends on locked@ | 73 | @depends on locked && patch@ |
70 | position gfp.p; | 74 | position gfp.p; |
71 | @@ | 75 | @@ |
72 | 76 | ||
73 | - GFP_KERNEL@p | 77 | - GFP_KERNEL@p |
74 | + GFP_ATOMIC | 78 | + GFP_ATOMIC |
79 | |||
80 | @depends on locked && !patch@ | ||
81 | position gfp.p; | ||
82 | @@ | ||
83 | |||
84 | * GFP_KERNEL@p | ||
85 | |||
86 | @script:python depends on !patch && org@ | ||
87 | p << gfp.p; | ||
88 | fn << gfp.fn; | ||
89 | p1 << locked.p1; | ||
90 | p2 << locked.p2; | ||
91 | @@ | ||
92 | |||
93 | cocci.print_main("lock",p1) | ||
94 | cocci.print_secs("call",p2) | ||
95 | cocci.print_secs("GFP_KERNEL",p) | ||
96 | |||
97 | @script:python depends on !patch && report@ | ||
98 | p << gfp.p; | ||
99 | fn << gfp.fn; | ||
100 | p1 << locked.p1; | ||
101 | p2 << locked.p2; | ||
102 | @@ | ||
103 | |||
104 | msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line) | ||
105 | coccilib.report.print_report(p[0], msg) | ||
75 | 106 |
scripts/coccinelle/locks/flags.cocci
1 | /// Find nested lock+irqsave functions that use the same flags variables | 1 | /// Find nested lock+irqsave functions that use the same flags variables |
2 | /// | 2 | /// |
3 | // Confidence: High | 3 | // Confidence: High |
4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 4 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 6 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
7 | // URL: http://coccinelle.lip6.fr/ | 7 | // URL: http://coccinelle.lip6.fr/ |
8 | // Comments: | 8 | // Comments: |
9 | // Options: -no_includes -include_headers | 9 | // Options: -no_includes -include_headers |
10 | 10 | ||
11 | virtual context | 11 | virtual context |
12 | virtual org | 12 | virtual org |
13 | virtual report | 13 | virtual report |
14 | 14 | ||
15 | @r@ | 15 | @r exists@ |
16 | expression lock1,lock2,flags; | 16 | expression lock1,lock2,flags; |
17 | position p1,p2; | 17 | position p1,p2; |
18 | @@ | 18 | @@ |
19 | 19 | ||
20 | ( | 20 | ( |
21 | spin_lock_irqsave@p1(lock1,flags) | 21 | spin_lock_irqsave@p1(lock1,flags) |
22 | | | 22 | | |
23 | read_lock_irqsave@p1(lock1,flags) | 23 | read_lock_irqsave@p1(lock1,flags) |
24 | | | 24 | | |
25 | write_lock_irqsave@p1(lock1,flags) | 25 | write_lock_irqsave@p1(lock1,flags) |
26 | ) | 26 | ) |
27 | ... when != flags | 27 | ... when != flags |
28 | ( | 28 | ( |
29 | spin_lock_irqsave(lock1,flags) | 29 | spin_lock_irqsave(lock1,flags) |
30 | | | 30 | | |
31 | read_lock_irqsave(lock1,flags) | 31 | read_lock_irqsave(lock1,flags) |
32 | | | 32 | | |
33 | write_lock_irqsave(lock1,flags) | 33 | write_lock_irqsave(lock1,flags) |
34 | | | 34 | | |
35 | spin_lock_irqsave@p2(lock2,flags) | 35 | spin_lock_irqsave@p2(lock2,flags) |
36 | | | 36 | | |
37 | read_lock_irqsave@p2(lock2,flags) | 37 | read_lock_irqsave@p2(lock2,flags) |
38 | | | 38 | | |
39 | write_lock_irqsave@p2(lock2,flags) | 39 | write_lock_irqsave@p2(lock2,flags) |
40 | ) | 40 | ) |
41 | 41 | ||
42 | @d@ | 42 | @d exists@ |
43 | expression f <= r.flags; | 43 | expression f <= r.flags; |
44 | expression lock1,lock2,flags; | 44 | expression lock1,lock2,flags; |
45 | position r.p1, r.p2; | 45 | position r.p1, r.p2; |
46 | @@ | 46 | @@ |
47 | 47 | ||
48 | ( | 48 | ( |
49 | *spin_lock_irqsave@p1(lock1,flags) | 49 | *spin_lock_irqsave@p1(lock1,flags) |
50 | | | 50 | | |
51 | *read_lock_irqsave@p1(lock1,flags) | 51 | *read_lock_irqsave@p1(lock1,flags) |
52 | | | 52 | | |
53 | *write_lock_irqsave@p1(lock1,flags) | 53 | *write_lock_irqsave@p1(lock1,flags) |
54 | ) | 54 | ) |
55 | ... when != f | 55 | ... when != f |
56 | ( | 56 | ( |
57 | *spin_lock_irqsave@p2(lock2,flags) | 57 | *spin_lock_irqsave@p2(lock2,flags) |
58 | | | 58 | | |
59 | *read_lock_irqsave@p2(lock2,flags) | 59 | *read_lock_irqsave@p2(lock2,flags) |
60 | | | 60 | | |
61 | *write_lock_irqsave@p2(lock2,flags) | 61 | *write_lock_irqsave@p2(lock2,flags) |
62 | ) | 62 | ) |
63 | 63 | ||
64 | // ---------------------------------------------------------------------- | 64 | // ---------------------------------------------------------------------- |
65 | 65 | ||
66 | @script:python depends on d && org@ | 66 | @script:python depends on d && org@ |
67 | p1 << r.p1; | 67 | p1 << r.p1; |
68 | p2 << r.p2; | 68 | p2 << r.p2; |
69 | @@ | 69 | @@ |
70 | 70 | ||
71 | cocci.print_main("original lock",p1) | 71 | cocci.print_main("original lock",p1) |
72 | cocci.print_secs("nested lock+irqsave that reuses flags",p2) | 72 | cocci.print_secs("nested lock+irqsave that reuses flags",p2) |
73 | 73 | ||
74 | @script:python depends on d && report@ | 74 | @script:python depends on d && report@ |
75 | p1 << r.p1; | 75 | p1 << r.p1; |
76 | p2 << r.p2; | 76 | p2 << r.p2; |
77 | @@ | 77 | @@ |
78 | 78 | ||
79 | msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line) | 79 | msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line) |
80 | coccilib.report.print_report(p2[0], msg) | 80 | coccilib.report.print_report(p2[0], msg) |
81 | 81 |
scripts/coccinelle/locks/mini_lock.cocci
1 | /// Find missing unlocks. This semantic match considers the specific case | 1 | /// Find missing unlocks. This semantic match considers the specific case |
2 | /// where the unlock is missing from an if branch, and there is a lock | 2 | /// where the unlock is missing from an if branch, and there is a lock |
3 | /// before the if and an unlock after the if. False positives are due to | 3 | /// before the if and an unlock after the if. False positives are due to |
4 | /// cases where the if branch represents a case where the function is | 4 | /// cases where the if branch represents a case where the function is |
5 | /// supposed to exit with the lock held, or where there is some preceding | 5 | /// supposed to exit with the lock held, or where there is some preceding |
6 | /// function call that releases the lock. | 6 | /// function call that releases the lock. |
7 | /// | 7 | /// |
8 | // Confidence: Moderate | 8 | // Confidence: Moderate |
9 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 9 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
10 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 10 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
11 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 11 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
12 | // URL: http://coccinelle.lip6.fr/ | 12 | // URL: http://coccinelle.lip6.fr/ |
13 | // Comments: | 13 | // Comments: |
14 | // Options: -no_includes -include_headers | 14 | // Options: -no_includes -include_headers |
15 | 15 | ||
16 | virtual context | ||
16 | virtual org | 17 | virtual org |
17 | virtual report | 18 | virtual report |
18 | 19 | ||
19 | @prelocked@ | 20 | @prelocked@ |
20 | position p1,p; | 21 | position p1,p; |
21 | expression E1; | 22 | expression E1; |
22 | @@ | 23 | @@ |
23 | 24 | ||
24 | ( | 25 | ( |
25 | mutex_lock@p1 | 26 | mutex_lock@p1 |
26 | | | 27 | | |
27 | mutex_trylock@p1 | 28 | mutex_trylock@p1 |
28 | | | 29 | | |
29 | spin_lock@p1 | 30 | spin_lock@p1 |
30 | | | 31 | | |
31 | spin_trylock@p1 | 32 | spin_trylock@p1 |
32 | | | 33 | | |
33 | read_lock@p1 | 34 | read_lock@p1 |
34 | | | 35 | | |
35 | read_trylock@p1 | 36 | read_trylock@p1 |
36 | | | 37 | | |
37 | write_lock@p1 | 38 | write_lock@p1 |
38 | | | 39 | | |
39 | write_trylock@p1 | 40 | write_trylock@p1 |
40 | | | 41 | | |
41 | read_lock_irq@p1 | 42 | read_lock_irq@p1 |
42 | | | 43 | | |
43 | write_lock_irq@p1 | 44 | write_lock_irq@p1 |
44 | | | 45 | | |
45 | read_lock_irqsave@p1 | 46 | read_lock_irqsave@p1 |
46 | | | 47 | | |
47 | write_lock_irqsave@p1 | 48 | write_lock_irqsave@p1 |
48 | | | 49 | | |
49 | spin_lock_irq@p1 | 50 | spin_lock_irq@p1 |
50 | | | 51 | | |
51 | spin_lock_irqsave@p1 | 52 | spin_lock_irqsave@p1 |
52 | ) (E1@p,...); | 53 | ) (E1@p,...); |
53 | 54 | ||
54 | @looped@ | 55 | @looped@ |
55 | position r; | 56 | position r; |
56 | @@ | 57 | @@ |
57 | 58 | ||
58 | for(...;...;...) { <+... return@r ...; ...+> } | 59 | for(...;...;...) { <+... return@r ...; ...+> } |
59 | 60 | ||
60 | @err@ | 61 | @err exists@ |
61 | expression E1; | 62 | expression E1; |
62 | position prelocked.p; | 63 | position prelocked.p; |
63 | position up != prelocked.p1; | 64 | position up != prelocked.p1; |
64 | position r!=looped.r; | 65 | position r!=looped.r; |
65 | identifier lock,unlock; | 66 | identifier lock,unlock; |
66 | @@ | 67 | @@ |
67 | 68 | ||
68 | lock(E1@p,...); | 69 | *lock(E1@p,...); |
69 | <+... when != E1 | 70 | <+... when != E1 |
70 | if (...) { | 71 | if (...) { |
71 | ... when != E1 | 72 | ... when != E1 |
72 | return@r ...; | 73 | * return@r ...; |
73 | } | 74 | } |
74 | ...+> | 75 | ...+> |
75 | unlock@up(E1,...); | 76 | *unlock@up(E1,...); |
76 | 77 | ||
77 | @script:python depends on org@ | 78 | @script:python depends on org@ |
78 | p << prelocked.p1; | 79 | p << prelocked.p1; |
79 | lock << err.lock; | 80 | lock << err.lock; |
80 | unlock << err.unlock; | 81 | unlock << err.unlock; |
81 | p2 << err.r; | 82 | p2 << err.r; |
82 | @@ | 83 | @@ |
83 | 84 | ||
84 | cocci.print_main(lock,p) | 85 | cocci.print_main(lock,p) |
85 | cocci.print_secs(unlock,p2) | 86 | cocci.print_secs(unlock,p2) |
86 | 87 | ||
87 | @script:python depends on report@ | 88 | @script:python depends on report@ |
88 | p << prelocked.p1; | 89 | p << prelocked.p1; |
89 | lock << err.lock; | 90 | lock << err.lock; |
90 | unlock << err.unlock; | 91 | unlock << err.unlock; |
91 | p2 << err.r; | 92 | p2 << err.r; |
92 | @@ | 93 | @@ |
93 | 94 | ||
94 | msg = "preceding lock on line %s" % (p[0].line) | 95 | msg = "preceding lock on line %s" % (p[0].line) |
95 | coccilib.report.print_report(p2[0],msg) | 96 | coccilib.report.print_report(p2[0],msg) |
96 | 97 |
scripts/coccinelle/misc/doubleinit.cocci
1 | /// Find duplicate field initializations. This has a high rate of false | 1 | /// Find duplicate field initializations. This has a high rate of false |
2 | /// positives due to #ifdefs, which Coccinelle is not aware of in a structure | 2 | /// positives due to #ifdefs, which Coccinelle is not aware of in a structure |
3 | /// initialization. | 3 | /// initialization. |
4 | /// | 4 | /// |
5 | // Confidence: Low | 5 | // Confidence: Low |
6 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 6 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
7 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 7 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
8 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 8 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
9 | // URL: http://coccinelle.lip6.fr/ | 9 | // URL: http://coccinelle.lip6.fr/ |
10 | // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise | 10 | // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise |
11 | // Options: -no_includes -include_headers | 11 | // Options: -no_includes -include_headers |
12 | 12 | ||
13 | virtual org | 13 | virtual org |
14 | virtual report | 14 | virtual report |
15 | 15 | ||
16 | @r@ | 16 | @r@ |
17 | identifier I, s, fld; | 17 | identifier I, s, fld; |
18 | position p0,p; | 18 | position p0,p; |
19 | expression E; | 19 | expression E; |
20 | @@ | 20 | @@ |
21 | 21 | ||
22 | struct I s =@p0 { ..., .fld@p = E, ...}; | 22 | struct I s =@p0 { ..., .fld@p = E, ...}; |
23 | 23 | ||
24 | @s@ | 24 | @s@ |
25 | identifier I, s, r.fld; | 25 | identifier I, s, r.fld; |
26 | position r.p0,p; | 26 | position r.p0,p; |
27 | expression E; | 27 | expression E; |
28 | @@ | 28 | @@ |
29 | 29 | ||
30 | struct I s =@p0 { ..., .fld@p = E, ...}; | 30 | struct I s =@p0 { ..., .fld@p = E, ...}; |
31 | 31 | ||
32 | @script:python depends on org@ | 32 | @script:python depends on org@ |
33 | p0 << r.p0; | 33 | p0 << r.p0; |
34 | fld << r.fld; | 34 | fld << r.fld; |
35 | ps << s.p; | 35 | ps << s.p; |
36 | pr << r.p; | 36 | pr << r.p; |
37 | @@ | 37 | @@ |
38 | 38 | ||
39 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): | 39 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): |
40 | cocci.print_main(fld,p0) | 40 | cocci.print_main(fld,p0) |
41 | cocci.print_secs("s",ps) | 41 | cocci.print_secs("s",ps) |
42 | cocci.print_secs("r",pr) | 42 | cocci.print_secs("r",pr) |
43 | 43 | ||
44 | @script:python depends on report@ | 44 | @script:python depends on report@ |
45 | p0 << r.p0; | 45 | p0 << r.p0; |
46 | fld << r.fld; | 46 | fld << r.fld; |
47 | ps << s.p; | 47 | ps << s.p; |
48 | pr << r.p; | 48 | pr << r.p; |
49 | @@ | 49 | @@ |
50 | 50 | ||
51 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): | 51 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): |
52 | msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line) | 52 | msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line) |
53 | coccilib.report.print_report(p0[0],msg) | 53 | coccilib.report.print_report(p0[0],msg) |
54 | 54 |
scripts/coccinelle/null/eno.cocci
1 | /// The various basic memory allocation functions don't return ERR_PTR | 1 | /// The various basic memory allocation functions don't return ERR_PTR |
2 | /// | 2 | /// |
3 | // Confidence: High | 3 | // Confidence: High |
4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | 4 | // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. |
5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | 5 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. |
6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | 6 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. |
7 | // URL: http://coccinelle.lip6.fr/ | 7 | // URL: http://coccinelle.lip6.fr/ |
8 | // Comments: | 8 | // Comments: |
9 | // Options: -no_includes -include_headers | 9 | // Options: -no_includes -include_headers |
10 | 10 | ||
11 | virtual patch | 11 | virtual patch |
12 | virtual context | ||
13 | virtual org | ||
14 | virtual report | ||
12 | 15 | ||
13 | @@ | 16 | @depends on patch@ |
14 | expression x,E; | 17 | expression x,E; |
15 | @@ | 18 | @@ |
16 | 19 | ||
17 | x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...) | 20 | x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...) |
18 | ... when != x = E | 21 | ... when != x = E |
19 | - IS_ERR(x) | 22 | - IS_ERR(x) |
20 | + !x | 23 | + !x |
24 | |||
25 | @r depends on !patch exists@ | ||
26 | expression x,E; | ||
27 | position p1,p2; | ||
28 | @@ | ||
29 | |||
30 | *x = \(kmalloc@p1\|kzalloc@p1\|kcalloc@p1\|kmem_cache_alloc@p1\|kmem_cache_zalloc@p1\|kmem_cache_alloc_node@p1\|kmalloc_node@p1\|kzalloc_node@p1\)(...) | ||
31 | ... when != x = E | ||
32 | * IS_ERR@p2(x) | ||
33 | |||
34 | @script:python depends on org@ | ||
35 | p1 << r.p1; | ||
36 | p2 << r.p2; | ||
37 | @@ | ||
38 | |||
39 | cocci.print_main("alloc call",p1) | ||
40 | cocci.print_secs("IS_ERR that should be NULL tests",p2) | ||
41 | |||
42 | @script:python depends on report@ | ||
43 | p1 << r.p1; | ||
44 | p2 << r.p2; | ||
45 | @@ | ||
46 | |||
47 | msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line) | ||
48 | coccilib.report.print_report(p2[0], msg) | ||
21 | 49 |
scripts/tags.sh
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # Generate tags or cscope files | 2 | # Generate tags or cscope files |
3 | # Usage tags.sh <mode> | 3 | # Usage tags.sh <mode> |
4 | # | 4 | # |
5 | # mode may be any of: tags, TAGS, cscope | 5 | # mode may be any of: tags, TAGS, cscope |
6 | # | 6 | # |
7 | # Uses the following environment variables: | 7 | # Uses the following environment variables: |
8 | # ARCH, SUBARCH, SRCARCH, srctree, src, obj | 8 | # ARCH, SUBARCH, SRCARCH, srctree, src, obj |
9 | 9 | ||
10 | if [ "$KBUILD_VERBOSE" = "1" ]; then | 10 | if [ "$KBUILD_VERBOSE" = "1" ]; then |
11 | set -x | 11 | set -x |
12 | fi | 12 | fi |
13 | 13 | ||
14 | # This is a duplicate of RCS_FIND_IGNORE without escaped '()' | 14 | # This is a duplicate of RCS_FIND_IGNORE without escaped '()' |
15 | ignore="( -name SCCS -o -name BitKeeper -o -name .svn -o \ | 15 | ignore="( -name SCCS -o -name BitKeeper -o -name .svn -o \ |
16 | -name CVS -o -name .pc -o -name .hg -o \ | 16 | -name CVS -o -name .pc -o -name .hg -o \ |
17 | -name .git ) \ | 17 | -name .git ) \ |
18 | -prune -o" | 18 | -prune -o" |
19 | 19 | ||
20 | # Do not use full path if we do not use O=.. builds | 20 | # Do not use full path if we do not use O=.. builds |
21 | # Use make O=. {tags|cscope} | 21 | # Use make O=. {tags|cscope} |
22 | # to force full paths for a non-O= build | 22 | # to force full paths for a non-O= build |
23 | if [ "${KBUILD_SRC}" = "" ]; then | 23 | if [ "${KBUILD_SRC}" = "" ]; then |
24 | tree= | 24 | tree= |
25 | else | 25 | else |
26 | tree=${srctree}/ | 26 | tree=${srctree}/ |
27 | fi | 27 | fi |
28 | 28 | ||
29 | # Find all available archs | 29 | # Find all available archs |
30 | find_all_archs() | 30 | find_all_archs() |
31 | { | 31 | { |
32 | ALLSOURCE_ARCHS="" | 32 | ALLSOURCE_ARCHS="" |
33 | for arch in `ls ${tree}arch`; do | 33 | for arch in `ls ${tree}arch`; do |
34 | ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/} | 34 | ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/} |
35 | done | 35 | done |
36 | } | 36 | } |
37 | 37 | ||
38 | # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH | 38 | # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH |
39 | if [ "${ALLSOURCE_ARCHS}" = "" ]; then | 39 | if [ "${ALLSOURCE_ARCHS}" = "" ]; then |
40 | ALLSOURCE_ARCHS=${SRCARCH} | 40 | ALLSOURCE_ARCHS=${SRCARCH} |
41 | elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then | 41 | elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then |
42 | find_all_archs | 42 | find_all_archs |
43 | fi | 43 | fi |
44 | 44 | ||
45 | # find sources in arch/$ARCH | 45 | # find sources in arch/$ARCH |
46 | find_arch_sources() | 46 | find_arch_sources() |
47 | { | 47 | { |
48 | for i in $archincludedir; do | 48 | for i in $archincludedir; do |
49 | prune="$prune -wholename $i -prune -o" | 49 | prune="$prune -wholename $i -prune -o" |
50 | done | 50 | done |
51 | find ${tree}arch/$1 $ignore $prune -name "$2" -print; | 51 | find ${tree}arch/$1 $ignore $prune -name "$2" -print; |
52 | } | 52 | } |
53 | 53 | ||
54 | # find sources in arch/$1/include | 54 | # find sources in arch/$1/include |
55 | find_arch_include_sources() | 55 | find_arch_include_sources() |
56 | { | 56 | { |
57 | include=$(find ${tree}arch/$1/ -name include -type d); | 57 | include=$(find ${tree}arch/$1/ -name include -type d); |
58 | if [ -n "$include" ]; then | 58 | if [ -n "$include" ]; then |
59 | archincludedir="$archincludedir $include" | 59 | archincludedir="$archincludedir $include" |
60 | find $include $ignore -name "$2" -print; | 60 | find $include $ignore -name "$2" -print; |
61 | fi | 61 | fi |
62 | } | 62 | } |
63 | 63 | ||
64 | # find sources in include/ | 64 | # find sources in include/ |
65 | find_include_sources() | 65 | find_include_sources() |
66 | { | 66 | { |
67 | find ${tree}include $ignore -name config -prune -o -name "$1" -print; | 67 | find ${tree}include $ignore -name config -prune -o -name "$1" -print; |
68 | } | 68 | } |
69 | 69 | ||
70 | # find sources in rest of tree | 70 | # find sources in rest of tree |
71 | # we could benefit from a list of dirs to search in here | 71 | # we could benefit from a list of dirs to search in here |
72 | find_other_sources() | 72 | find_other_sources() |
73 | { | 73 | { |
74 | find ${tree}* $ignore \ | 74 | find ${tree}* $ignore \ |
75 | \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \ | 75 | \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \ |
76 | -name "$1" -print; | 76 | -name "$1" -print; |
77 | } | 77 | } |
78 | 78 | ||
79 | find_sources() | 79 | find_sources() |
80 | { | 80 | { |
81 | find_arch_sources $1 "$2" | 81 | find_arch_sources $1 "$2" |
82 | } | 82 | } |
83 | 83 | ||
84 | all_sources() | 84 | all_sources() |
85 | { | 85 | { |
86 | find_arch_include_sources ${SRCARCH} '*.[chS]' | 86 | find_arch_include_sources ${SRCARCH} '*.[chS]' |
87 | if [ ! -z "$archinclude" ]; then | 87 | if [ ! -z "$archinclude" ]; then |
88 | find_arch_include_sources $archinclude '*.[chS]' | 88 | find_arch_include_sources $archinclude '*.[chS]' |
89 | fi | 89 | fi |
90 | find_include_sources '*.[chS]' | 90 | find_include_sources '*.[chS]' |
91 | for arch in $ALLSOURCE_ARCHS | 91 | for arch in $ALLSOURCE_ARCHS |
92 | do | 92 | do |
93 | find_sources $arch '*.[chS]' | 93 | find_sources $arch '*.[chS]' |
94 | done | 94 | done |
95 | find_other_sources '*.[chS]' | 95 | find_other_sources '*.[chS]' |
96 | } | 96 | } |
97 | 97 | ||
98 | all_kconfigs() | 98 | all_kconfigs() |
99 | { | 99 | { |
100 | for arch in $ALLSOURCE_ARCHS; do | 100 | for arch in $ALLSOURCE_ARCHS; do |
101 | find_sources $arch 'Kconfig*' | 101 | find_sources $arch 'Kconfig*' |
102 | done | 102 | done |
103 | find_other_sources 'Kconfig*' | 103 | find_other_sources 'Kconfig*' |
104 | } | 104 | } |
105 | 105 | ||
106 | all_defconfigs() | 106 | all_defconfigs() |
107 | { | 107 | { |
108 | find_sources $ALLSOURCE_ARCHS "defconfig" | 108 | find_sources $ALLSOURCE_ARCHS "defconfig" |
109 | } | 109 | } |
110 | 110 | ||
111 | docscope() | 111 | docscope() |
112 | { | 112 | { |
113 | (echo \-k; echo \-q; all_sources) > cscope.files | 113 | (echo \-k; echo \-q; all_sources) > cscope.files |
114 | cscope -b -f cscope.out | 114 | cscope -b -f cscope.out |
115 | } | 115 | } |
116 | 116 | ||
117 | dogtags() | 117 | dogtags() |
118 | { | 118 | { |
119 | all_sources | gtags -f - | 119 | all_sources | gtags -f - |
120 | } | 120 | } |
121 | 121 | ||
122 | exuberant() | 122 | exuberant() |
123 | { | 123 | { |
124 | all_sources | xargs $1 -a \ | 124 | all_sources | xargs $1 -a \ |
125 | -I __initdata,__exitdata,__acquires,__releases \ | 125 | -I __initdata,__exitdata,__acquires,__releases \ |
126 | -I __read_mostly,____cacheline_aligned \ | 126 | -I __read_mostly,____cacheline_aligned \ |
127 | -I ____cacheline_aligned_in_smp \ | 127 | -I ____cacheline_aligned_in_smp \ |
128 | -I ____cacheline_internodealigned_in_smp \ | 128 | -I ____cacheline_internodealigned_in_smp \ |
129 | -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ | 129 | -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ |
130 | -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ | 130 | -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ |
131 | --extra=+f --c-kinds=+px \ | 131 | --extra=+f --c-kinds=+px \ |
132 | --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ | 132 | --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ |
133 | --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ | 133 | --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ |
134 | --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ | 134 | --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ |
135 | --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' | 135 | --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ |
136 | --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ | ||
137 | --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ | ||
138 | --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ | ||
139 | --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ | ||
140 | --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ | ||
141 | --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ | ||
142 | --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ | ||
143 | --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
144 | --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
145 | --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ | ||
146 | --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ | ||
147 | --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ | ||
148 | --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ | ||
149 | --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ | ||
150 | --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ | ||
151 | --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
152 | --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ | ||
153 | --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ | ||
154 | --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ | ||
155 | --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ | ||
156 | --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' | ||
136 | 157 | ||
137 | all_kconfigs | xargs $1 -a \ | 158 | all_kconfigs | xargs $1 -a \ |
138 | --langdef=kconfig --language-force=kconfig \ | 159 | --langdef=kconfig --language-force=kconfig \ |
139 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' | 160 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' |
140 | 161 | ||
141 | all_kconfigs | xargs $1 -a \ | 162 | all_kconfigs | xargs $1 -a \ |
142 | --langdef=kconfig --language-force=kconfig \ | 163 | --langdef=kconfig --language-force=kconfig \ |
143 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' | 164 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' |
144 | 165 | ||
145 | all_defconfigs | xargs -r $1 -a \ | 166 | all_defconfigs | xargs -r $1 -a \ |
146 | --langdef=dotconfig --language-force=dotconfig \ | 167 | --langdef=dotconfig --language-force=dotconfig \ |
147 | --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' | 168 | --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' |
148 | 169 | ||
170 | # Remove structure forward declarations. | ||
171 | LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags | ||
149 | } | 172 | } |
150 | 173 | ||
151 | emacs() | 174 | emacs() |
152 | { | 175 | { |
153 | all_sources | xargs $1 -a \ | 176 | all_sources | xargs $1 -a \ |
154 | --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ | 177 | --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ |
155 | --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ | 178 | --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ |
156 | --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ | 179 | --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ |
157 | --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' | 180 | --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ |
181 | --regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \ | ||
182 | --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ | ||
183 | --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ | ||
184 | --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ | ||
185 | --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ | ||
186 | --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ | ||
187 | --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ | ||
188 | --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
189 | --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
190 | --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ | ||
191 | --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ | ||
192 | --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ | ||
193 | --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ | ||
194 | --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ | ||
195 | --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ | ||
196 | --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ | ||
197 | --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ | ||
198 | --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ | ||
199 | --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ | ||
200 | --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ | ||
201 | --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' | ||
158 | 202 | ||
159 | all_kconfigs | xargs $1 -a \ | 203 | all_kconfigs | xargs $1 -a \ |
160 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' | 204 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' |
161 | 205 | ||
162 | all_kconfigs | xargs $1 -a \ | 206 | all_kconfigs | xargs $1 -a \ |
163 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' | 207 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' |
164 | 208 | ||
165 | all_defconfigs | xargs -r $1 -a \ | 209 | all_defconfigs | xargs -r $1 -a \ |
166 | --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' | 210 | --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' |
167 | } | 211 | } |
168 | 212 | ||
169 | xtags() | 213 | xtags() |
170 | { | 214 | { |
171 | if $1 --version 2>&1 | grep -iq exuberant; then | 215 | if $1 --version 2>&1 | grep -iq exuberant; then |
172 | exuberant $1 | 216 | exuberant $1 |
173 | elif $1 --version 2>&1 | grep -iq emacs; then | 217 | elif $1 --version 2>&1 | grep -iq emacs; then |
174 | emacs $1 | 218 | emacs $1 |
175 | else | 219 | else |
176 | all_sources | xargs $1 -a | 220 | all_sources | xargs $1 -a |
177 | fi | 221 | fi |
178 | } | 222 | } |
179 | 223 | ||
180 | 224 | ||
181 | # Support um (which uses SUBARCH) | 225 | # Support um (which uses SUBARCH) |
182 | if [ "${ARCH}" = "um" ]; then | 226 | if [ "${ARCH}" = "um" ]; then |
183 | if [ "$SUBARCH" = "i386" ]; then | 227 | if [ "$SUBARCH" = "i386" ]; then |
184 | archinclude=x86 | 228 | archinclude=x86 |
185 | elif [ "$SUBARCH" = "x86_64" ]; then | 229 | elif [ "$SUBARCH" = "x86_64" ]; then |
186 | archinclude=x86 | 230 | archinclude=x86 |
187 | else | 231 | else |
188 | archinclude=${SUBARCH} | 232 | archinclude=${SUBARCH} |
189 | fi | 233 | fi |
190 | fi | 234 | fi |
191 | 235 | ||
192 | case "$1" in | 236 | case "$1" in |
193 | "cscope") | 237 | "cscope") |
194 | docscope | 238 | docscope |
195 | ;; | 239 | ;; |
196 | 240 | ||
197 | "gtags") | 241 | "gtags") |
198 | dogtags | 242 | dogtags |
199 | ;; | 243 | ;; |
200 | 244 | ||
201 | "tags") | 245 | "tags") |
202 | rm -f tags | 246 | rm -f tags |
203 | xtags ctags | 247 | xtags ctags |
204 | ;; | 248 | ;; |
205 | 249 | ||
206 | "TAGS") | 250 | "TAGS") |
207 | rm -f TAGS | 251 | rm -f TAGS |
208 | xtags etags | 252 | xtags etags |
209 | ;; | 253 | ;; |
210 | esac | 254 | esac |
211 | 255 |