Commit 82c4340b0a3ccf090ef38fa111363018cf0594c8

Authored by Nicolas Palix
Committed by Michal Marek
1 parent f853f8305b

Add scripts/coccinelle/deref_null.cocci

Add a Coccinelle file to identify the dereferences of NULL variables

This semantic patch identifies when a variable is known to be NULL
after a test, but it is still dereferenced later.

Signed-off-by: Nicolas Palix <npalix@diku.dk>
Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: Michal Marek <mmarek@suse.cz>

Showing 1 changed file with 293 additions and 0 deletions Side-by-side Diff

scripts/coccinelle/deref_null.cocci
  1 +///
  2 +/// A variable is dereference under a NULL test.
  3 +/// Even though it is know to be NULL.
  4 +///
  5 +// Confidence: Moderate
  6 +// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
  7 +// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
  8 +// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
  9 +// URL: http://coccinelle.lip6.fr/
  10 +// Comments: -I ... -all_includes can give more complete results
  11 +// Options:
  12 +
  13 +virtual context
  14 +virtual patch
  15 +virtual org
  16 +virtual report
  17 +
  18 +@initialize:python depends on !context && patch && !org && !report@
  19 +
  20 +import sys
  21 +print >> sys.stderr, "This semantic patch does not support the 'patch' mode."
  22 +
  23 +@depends on patch@
  24 +@@
  25 +
  26 +this_rule_should_never_matches();
  27 +
  28 +@ifm depends on !patch@
  29 +expression *E;
  30 +statement S1,S2;
  31 +position p1;
  32 +@@
  33 +
  34 +if@p1 ((E == NULL && ...) || ...) S1 else S2
  35 +
  36 +// The following two rules are separate, because both can match a single
  37 +// expression in different ways
  38 +@pr1 depends on !patch expression@
  39 +expression *ifm.E;
  40 +identifier f;
  41 +position p1;
  42 +@@
  43 +
  44 + (E != NULL && ...) ? <+...E->f@p1...+> : ...
  45 +
  46 +@pr2 depends on !patch expression@
  47 +expression *ifm.E;
  48 +identifier f;
  49 +position p2;
  50 +@@
  51 +
  52 +(
  53 + (E != NULL) && ... && <+...E->f@p2...+>
  54 +|
  55 + (E == NULL) || ... || <+...E->f@p2...+>
  56 +|
  57 + sizeof(<+...E->f@p2...+>)
  58 +)
  59 +
  60 +// For org and report modes
  61 +
  62 +@r depends on !context && !patch && (org || report) exists@
  63 +expression subE <= ifm.E;
  64 +expression *ifm.E;
  65 +expression E1,E2;
  66 +identifier f;
  67 +statement S1,S2,S3,S4;
  68 +iterator iter;
  69 +position p!={pr1.p1,pr2.p2};
  70 +position ifm.p1;
  71 +@@
  72 +
  73 +if@p1 ((E == NULL && ...) || ...)
  74 +{
  75 + ... when != if (...) S1 else S2
  76 +(
  77 + iter(subE,...) S4 // no use
  78 +|
  79 + list_remove_head(E2,subE,...)
  80 +|
  81 + subE = E1
  82 +|
  83 + for(subE = E1;...;...) S4
  84 +|
  85 + subE++
  86 +|
  87 + ++subE
  88 +|
  89 + --subE
  90 +|
  91 + subE--
  92 +|
  93 + &subE
  94 +|
  95 + E->f@p // bad use
  96 +)
  97 + ... when any
  98 + return ...;
  99 +}
  100 +else S3
  101 +
  102 +@script:python depends on !context && !patch && !org && report@
  103 +p << r.p;
  104 +p1 << ifm.p1;
  105 +x << ifm.E;
  106 +@@
  107 +
  108 +msg="ERROR: %s is NULL but dereferenced." % (x)
  109 +coccilib.report.print_report(p[0], msg)
  110 +cocci.include_match(False)
  111 +
  112 +@script:python depends on !context && !patch && org && !report@
  113 +p << r.p;
  114 +p1 << ifm.p1;
  115 +x << ifm.E;
  116 +@@
  117 +
  118 +msg="ERROR: %s is NULL but dereferenced." % (x)
  119 +msg_safe=msg.replace("[","@(").replace("]",")")
  120 +cocci.print_main(msg_safe,p)
  121 +cocci.include_match(False)
  122 +
  123 +@s depends on !context && !patch && (org || report) exists@
  124 +expression subE <= ifm.E;
  125 +expression *ifm.E;
  126 +expression E1,E2;
  127 +identifier f;
  128 +statement S1,S2,S3,S4;
  129 +iterator iter;
  130 +position p!={pr1.p1,pr2.p2};
  131 +position ifm.p1;
  132 +@@
  133 +
  134 +if@p1 ((E == NULL && ...) || ...)
  135 +{
  136 + ... when != if (...) S1 else S2
  137 +(
  138 + iter(subE,...) S4 // no use
  139 +|
  140 + list_remove_head(E2,subE,...)
  141 +|
  142 + subE = E1
  143 +|
  144 + for(subE = E1;...;...) S4
  145 +|
  146 + subE++
  147 +|
  148 + ++subE
  149 +|
  150 + --subE
  151 +|
  152 + subE--
  153 +|
  154 + &subE
  155 +|
  156 + E->f@p // bad use
  157 +)
  158 + ... when any
  159 +}
  160 +else S3
  161 +
  162 +@script:python depends on !context && !patch && !org && report@
  163 +p << s.p;
  164 +p1 << ifm.p1;
  165 +x << ifm.E;
  166 +@@
  167 +
  168 +msg="ERROR: %s is NULL but dereferenced." % (x)
  169 +coccilib.report.print_report(p[0], msg)
  170 +
  171 +@script:python depends on !context && !patch && org && !report@
  172 +p << s.p;
  173 +p1 << ifm.p1;
  174 +x << ifm.E;
  175 +@@
  176 +
  177 +msg="ERROR: %s is NULL but dereferenced." % (x)
  178 +msg_safe=msg.replace("[","@(").replace("]",")")
  179 +cocci.print_main(msg_safe,p)
  180 +
  181 +// For context mode
  182 +
  183 +@depends on context && !patch && !org && !report exists@
  184 +expression subE <= ifm.E;
  185 +expression *ifm.E;
  186 +expression E1,E2;
  187 +identifier f;
  188 +statement S1,S2,S3,S4;
  189 +iterator iter;
  190 +position p!={pr1.p1,pr2.p2};
  191 +position ifm.p1;
  192 +@@
  193 +
  194 +if@p1 ((E == NULL && ...) || ...)
  195 +{
  196 + ... when != if (...) S1 else S2
  197 +(
  198 + iter(subE,...) S4 // no use
  199 +|
  200 + list_remove_head(E2,subE,...)
  201 +|
  202 + subE = E1
  203 +|
  204 + for(subE = E1;...;...) S4
  205 +|
  206 + subE++
  207 +|
  208 + ++subE
  209 +|
  210 + --subE
  211 +|
  212 + subE--
  213 +|
  214 + &subE
  215 +|
  216 +* E->f@p // bad use
  217 +)
  218 + ... when any
  219 + return ...;
  220 +}
  221 +else S3
  222 +
  223 +// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
  224 +// It is need because the previous rule as already made a "change".
  225 +
  226 +@ifm1 depends on !patch@
  227 +expression *E;
  228 +statement S1,S2;
  229 +position p1;
  230 +@@
  231 +
  232 +if@p1 ((E == NULL && ...) || ...) S1 else S2
  233 +
  234 +@pr11 depends on !patch expression@
  235 +expression *ifm1.E;
  236 +identifier f;
  237 +position p1;
  238 +@@
  239 +
  240 + (E != NULL && ...) ? <+...E->f@p1...+> : ...
  241 +
  242 +@pr12 depends on !patch expression@
  243 +expression *ifm1.E;
  244 +identifier f;
  245 +position p2;
  246 +@@
  247 +
  248 +(
  249 + (E != NULL) && ... && <+...E->f@p2...+>
  250 +|
  251 + (E == NULL) || ... || <+...E->f@p2...+>
  252 +|
  253 + sizeof(<+...E->f@p2...+>)
  254 +)
  255 +
  256 +@depends on context && !patch && !org && !report exists@
  257 +expression subE <= ifm1.E;
  258 +expression *ifm1.E;
  259 +expression E1,E2;
  260 +identifier f;
  261 +statement S1,S2,S3,S4;
  262 +iterator iter;
  263 +position p!={pr11.p1,pr12.p2};
  264 +position ifm1.p1;
  265 +@@
  266 +
  267 +if@p1 ((E == NULL && ...) || ...)
  268 +{
  269 + ... when != if (...) S1 else S2
  270 +(
  271 + iter(subE,...) S4 // no use
  272 +|
  273 + list_remove_head(E2,subE,...)
  274 +|
  275 + subE = E1
  276 +|
  277 + for(subE = E1;...;...) S4
  278 +|
  279 + subE++
  280 +|
  281 + ++subE
  282 +|
  283 + --subE
  284 +|
  285 + subE--
  286 +|
  287 + &subE
  288 +|
  289 +* E->f@p // bad use
  290 +)
  291 + ... when any
  292 +}
  293 +else S3