-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Nicolas Palix
authored and
Michal Marek
committed
Jun 11, 2010
1 parent
f853f83
commit 82c4340
Showing
1 changed file
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
/// | ||
/// A variable is dereference under a NULL test. | ||
/// Even though it is know to be NULL. | ||
/// | ||
// Confidence: Moderate | ||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
// URL: http://coccinelle.lip6.fr/ | ||
// Comments: -I ... -all_includes can give more complete results | ||
// Options: | ||
|
||
virtual context | ||
virtual patch | ||
virtual org | ||
virtual report | ||
|
||
@initialize:python depends on !context && patch && !org && !report@ | ||
import sys | ||
print >> sys.stderr, "This semantic patch does not support the 'patch' mode." | ||
@depends on patch@ | ||
@@ | ||
this_rule_should_never_matches(); | ||
@ifm depends on !patch@ | ||
expression *E; | ||
statement S1,S2; | ||
position p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) S1 else S2 | ||
|
||
// The following two rules are separate, because both can match a single | ||
// expression in different ways | ||
@pr1 depends on !patch expression@ | ||
expression *ifm.E; | ||
identifier f; | ||
position p1; | ||
@@ | ||
|
||
(E != NULL && ...) ? <+...E->f@p1...+> : ... | ||
|
||
@pr2 depends on !patch expression@ | ||
expression *ifm.E; | ||
identifier f; | ||
position p2; | ||
@@ | ||
|
||
( | ||
(E != NULL) && ... && <+...E->f@p2...+> | ||
| | ||
(E == NULL) || ... || <+...E->f@p2...+> | ||
| | ||
sizeof(<+...E->f@p2...+>) | ||
) | ||
|
||
// For org and report modes | ||
|
||
@r depends on !context && !patch && (org || report) exists@ | ||
expression subE <= ifm.E; | ||
expression *ifm.E; | ||
expression E1,E2; | ||
identifier f; | ||
statement S1,S2,S3,S4; | ||
iterator iter; | ||
position p!={pr1.p1,pr2.p2}; | ||
position ifm.p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) | ||
{ | ||
... when != if (...) S1 else S2 | ||
( | ||
iter(subE,...) S4 // no use | ||
| | ||
list_remove_head(E2,subE,...) | ||
| | ||
subE = E1 | ||
| | ||
for(subE = E1;...;...) S4 | ||
| | ||
subE++ | ||
| | ||
++subE | ||
| | ||
--subE | ||
| | ||
subE-- | ||
| | ||
&subE | ||
| | ||
E->f@p // bad use | ||
) | ||
... when any | ||
return ...; | ||
} | ||
else S3 | ||
|
||
@script:python depends on !context && !patch && !org && report@ | ||
p << r.p; | ||
p1 << ifm.p1; | ||
x << ifm.E; | ||
@@ | ||
msg="ERROR: %s is NULL but dereferenced." % (x) | ||
coccilib.report.print_report(p[0], msg) | ||
cocci.include_match(False) | ||
@script:python depends on !context && !patch && org && !report@ | ||
p << r.p; | ||
p1 << ifm.p1; | ||
x << ifm.E; | ||
@@ | ||
msg="ERROR: %s is NULL but dereferenced." % (x) | ||
msg_safe=msg.replace("[","@(").replace("]",")") | ||
cocci.print_main(msg_safe,p) | ||
cocci.include_match(False) | ||
@s depends on !context && !patch && (org || report) exists@ | ||
expression subE <= ifm.E; | ||
expression *ifm.E; | ||
expression E1,E2; | ||
identifier f; | ||
statement S1,S2,S3,S4; | ||
iterator iter; | ||
position p!={pr1.p1,pr2.p2}; | ||
position ifm.p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) | ||
{ | ||
... when != if (...) S1 else S2 | ||
( | ||
iter(subE,...) S4 // no use | ||
| | ||
list_remove_head(E2,subE,...) | ||
| | ||
subE = E1 | ||
| | ||
for(subE = E1;...;...) S4 | ||
| | ||
subE++ | ||
| | ||
++subE | ||
| | ||
--subE | ||
| | ||
subE-- | ||
| | ||
&subE | ||
| | ||
E->f@p // bad use | ||
) | ||
... when any | ||
} | ||
else S3 | ||
|
||
@script:python depends on !context && !patch && !org && report@ | ||
p << s.p; | ||
p1 << ifm.p1; | ||
x << ifm.E; | ||
@@ | ||
msg="ERROR: %s is NULL but dereferenced." % (x) | ||
coccilib.report.print_report(p[0], msg) | ||
@script:python depends on !context && !patch && org && !report@ | ||
p << s.p; | ||
p1 << ifm.p1; | ||
x << ifm.E; | ||
@@ | ||
msg="ERROR: %s is NULL but dereferenced." % (x) | ||
msg_safe=msg.replace("[","@(").replace("]",")") | ||
cocci.print_main(msg_safe,p) | ||
// For context mode | ||
@depends on context && !patch && !org && !report exists@ | ||
expression subE <= ifm.E; | ||
expression *ifm.E; | ||
expression E1,E2; | ||
identifier f; | ||
statement S1,S2,S3,S4; | ||
iterator iter; | ||
position p!={pr1.p1,pr2.p2}; | ||
position ifm.p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) | ||
{ | ||
... when != if (...) S1 else S2 | ||
( | ||
iter(subE,...) S4 // no use | ||
| | ||
list_remove_head(E2,subE,...) | ||
| | ||
subE = E1 | ||
| | ||
for(subE = E1;...;...) S4 | ||
| | ||
subE++ | ||
| | ||
++subE | ||
| | ||
--subE | ||
| | ||
subE-- | ||
| | ||
&subE | ||
| | ||
* E->f@p // bad use | ||
) | ||
... when any | ||
return ...; | ||
} | ||
else S3 | ||
|
||
// The following three rules are duplicates of ifm, pr1 and pr2 respectively. | ||
// It is need because the previous rule as already made a "change". | ||
|
||
@ifm1 depends on !patch@ | ||
expression *E; | ||
statement S1,S2; | ||
position p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) S1 else S2 | ||
|
||
@pr11 depends on !patch expression@ | ||
expression *ifm1.E; | ||
identifier f; | ||
position p1; | ||
@@ | ||
|
||
(E != NULL && ...) ? <+...E->f@p1...+> : ... | ||
|
||
@pr12 depends on !patch expression@ | ||
expression *ifm1.E; | ||
identifier f; | ||
position p2; | ||
@@ | ||
|
||
( | ||
(E != NULL) && ... && <+...E->f@p2...+> | ||
| | ||
(E == NULL) || ... || <+...E->f@p2...+> | ||
| | ||
sizeof(<+...E->f@p2...+>) | ||
) | ||
|
||
@depends on context && !patch && !org && !report exists@ | ||
expression subE <= ifm1.E; | ||
expression *ifm1.E; | ||
expression E1,E2; | ||
identifier f; | ||
statement S1,S2,S3,S4; | ||
iterator iter; | ||
position p!={pr11.p1,pr12.p2}; | ||
position ifm1.p1; | ||
@@ | ||
|
||
if@p1 ((E == NULL && ...) || ...) | ||
{ | ||
... when != if (...) S1 else S2 | ||
( | ||
iter(subE,...) S4 // no use | ||
| | ||
list_remove_head(E2,subE,...) | ||
| | ||
subE = E1 | ||
| | ||
for(subE = E1;...;...) S4 | ||
| | ||
subE++ | ||
| | ||
++subE | ||
| | ||
--subE | ||
| | ||
subE-- | ||
| | ||
&subE | ||
| | ||
* E->f@p // bad use | ||
) | ||
... when any | ||
} | ||
else S3 |