Commit 408e0578 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 287b901d 29a36d4d
...@@ -102,9 +102,15 @@ or ...@@ -102,9 +102,15 @@ or
make coccicheck COCCI=<my_SP.cocci> MODE=report make coccicheck COCCI=<my_SP.cocci> MODE=report
Using Coccinelle on (modified) files Controlling Which Files are Processed by Coccinelle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default the entire kernel source tree is checked.
To apply Coccinelle to a specific directory, M= can be used.
For example, to check drivers/net/wireless/ one may write:
make coccicheck M=drivers/net/wireless/
To apply Coccinelle on a file basis, instead of a directory basis, the To apply Coccinelle on a file basis, instead of a directory basis, the
following command may be used: following command may be used:
......
...@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then ...@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
# FLAGS="-ignore_unknown_options -very_quiet" # FLAGS="-ignore_unknown_options -very_quiet"
# OPTIONS=$* # OPTIONS=$*
# Workaround for Coccinelle < 0.2.3 if [ "$KBUILD_EXTMOD" = "" ] ; then
FLAGS="-I $srctree/include -very_quiet" # Workaround for Coccinelle < 0.2.3
shift $(( $# - 1 )) FLAGS="-I $srctree/include -very_quiet"
OPTIONS=$1 shift $(( $# - 1 ))
OPTIONS=$1
else
echo M= is not currently supported when C=1 or C=2
exit 1
fi
else else
ONLINE=0 ONLINE=0
FLAGS="-very_quiet" FLAGS="-very_quiet"
OPTIONS="-dir $srctree" if [ "$KBUILD_EXTMOD" = "" ] ; then
OPTIONS="-dir $srctree"
else
OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include"
fi
fi fi
if [ ! -x "$SPATCH" ]; then if [ ! -x "$SPATCH" ]; then
......
/// Reimplement a call to devm_request_mem_region followed by a call to ioremap
/// or ioremap_nocache by a call to devm_request_and_ioremap.
/// Devm_request_and_ioremap was introduced in
/// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0. It makes the code much more
/// concise.
///
///
// Confidence: High
// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: -no_includes -include_headers
virtual patch
virtual org
virtual report
virtual context
@nm@
expression myname;
identifier i;
@@
struct platform_driver i = { .driver = { .name = myname } };
@depends on patch@
expression dev,res,size;
@@
-if (!devm_request_mem_region(dev, res->start, size,
- \(res->name\|dev_name(dev)\))) {
- ...
- return ...;
-}
... when != res->start
(
-devm_ioremap(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
|
-devm_ioremap_nocache(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
)
... when any
when != res->start
// this rule is separate from the previous one, because a single file can
// have multiple values of myname
@depends on patch@
expression dev,res,size;
expression nm.myname;
@@
-if (!devm_request_mem_region(dev, res->start, size,myname)) {
- ...
- return ...;
-}
... when != res->start
(
-devm_ioremap(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
|
-devm_ioremap_nocache(dev,res->start,size)
+devm_request_and_ioremap(dev,res)
)
... when any
when != res->start
@pb depends on org || report || context@
expression dev,res,size;
expression nm.myname;
position p1,p2;
@@
*if
(!devm_request_mem_region@p1(dev, res->start, size,
\(res->name\|dev_name(dev)\|myname\))) {
...
return ...;
}
... when != res->start
(
*devm_ioremap@p2(dev,res->start,size)
|
*devm_ioremap_nocache@p2(dev,res->start,size)
)
... when any
when != res->start
@script:python depends on org@
p1 << pb.p1;
p2 << pb.p2;
@@
cocci.print_main("INFO: replace by devm_request_and_ioremap",p1)
cocci.print_secs("",p2)
@script:python depends on report@
p1 << pb.p1;
p2 << pb.p2;
@@
msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line)
coccilib.report.print_report(p1[0],msg)
/// Use kstrdup rather than duplicating its implementation /// Use kstrdup rather than duplicating its implementation
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@@ @depends on patch@
expression from,to; expression from,to;
expression flag,E1,E2; expression flag,E1,E2;
statement S; statement S;
...@@ -23,7 +26,7 @@ statement S; ...@@ -23,7 +26,7 @@ statement S;
... when != \(from = E2 \| to = E2 \) ... when != \(from = E2 \| to = E2 \)
- strcpy(to, from); - strcpy(to, from);
@@ @depends on patch@
expression x,from,to; expression x,from,to;
expression flag,E1,E2,E3; expression flag,E1,E2,E3;
statement S; statement S;
...@@ -37,3 +40,65 @@ statement S; ...@@ -37,3 +40,65 @@ statement S;
if (to==NULL || ...) S if (to==NULL || ...) S
... when != \(x = E3 \| from = E3 \| to = E3 \) ... when != \(x = E3 \| from = E3 \| to = E3 \)
- memcpy(to, from, x); - memcpy(to, from, x);
// ---------------------------------------------------------------------
@r1 depends on !patch exists@
expression from,to;
expression flag,E1,E2;
statement S;
position p1,p2;
@@
* to = kmalloc@p1(strlen(from) + 1,flag);
... when != \(from = E1 \| to = E1 \)
if (to==NULL || ...) S
... when != \(from = E2 \| to = E2 \)
* strcpy@p2(to, from);
@r2 depends on !patch exists@
expression x,from,to;
expression flag,E1,E2,E3;
statement S;
position p1,p2;
@@
* x = strlen(from) + 1;
... when != \( x = E1 \| from = E1 \)
* to = \(kmalloc@p1\|kzalloc@p2\)(x,flag);
... when != \(x = E2 \| from = E2 \| to = E2 \)
if (to==NULL || ...) S
... when != \(x = E3 \| from = E3 \| to = E3 \)
* memcpy@p2(to, from, x);
@script:python depends on org@
p1 << r1.p1;
p2 << r1.p2;
@@
cocci.print_main("WARNING opportunity for kstrdep",p1)
cocci.print_secs("strcpy",p2)
@script:python depends on org@
p1 << r2.p1;
p2 << r2.p2;
@@
cocci.print_main("WARNING opportunity for kstrdep",p1)
cocci.print_secs("memcpy",p2)
@script:python depends on report@
p1 << r1.p1;
p2 << r1.p2;
@@
msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)
@script:python depends on report@
p1 << r2.p1;
p2 << r2.p2;
@@
msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)
/// Use kmemdup rather than duplicating its implementation /// Use kmemdup rather than duplicating its implementation
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@r1@ @r1@
expression from,to; expression from,to;
...@@ -28,7 +31,7 @@ position p; ...@@ -28,7 +31,7 @@ position p;
... when != \( x = E1 \| from = E1 \) ... when != \( x = E1 \| from = E1 \)
to = \(kmalloc@p\|kzalloc@p\)(x,flag); to = \(kmalloc@p\|kzalloc@p\)(x,flag);
@@ @depends on patch@
expression from,to,size,flag; expression from,to,size,flag;
position p != {r1.p,r2.p}; position p != {r1.p,r2.p};
statement S; statement S;
...@@ -38,3 +41,26 @@ statement S; ...@@ -38,3 +41,26 @@ statement S;
+ to = kmemdup(from,size,flag); + to = kmemdup(from,size,flag);
if (to==NULL || ...) S if (to==NULL || ...) S
- memcpy(to, from, size); - memcpy(to, from, size);
@r depends on !patch@
expression from,to,size,flag;
position p != {r1.p,r2.p};
statement S;
@@
* to = \(kmalloc@p\|kzalloc@p\)(size,flag);
to = kmemdup(from,size,flag);
if (to==NULL || ...) S
* memcpy(to, from, size);
@script:python depends on org@
p << r.p;
@@
coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep")
@script:python depends on report@
p << r.p;
@@
coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep")
/// Use kmemdup_user rather than duplicating its implementation /// Use memdup_user rather than duplicating its implementation
/// This is a little bit restricted to reduce false positives /// This is a little bit restricted to reduce false positives
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@@ @depends on patch@
expression from,to,size,flag; expression from,to,size,flag;
position p;
identifier l1,l2; identifier l1,l2;
@@ @@
- to = \(kmalloc@p\|kzalloc@p\)(size,flag); - to = \(kmalloc\|kzalloc\)(size,flag);
+ to = memdup_user(from,size); + to = memdup_user(from,size);
if ( if (
- to==NULL - to==NULL
...@@ -33,3 +35,26 @@ identifier l1,l2; ...@@ -33,3 +35,26 @@ identifier l1,l2;
- -EFAULT - -EFAULT
- ...+> - ...+>
- } - }
@r depends on !patch@
expression from,to,size,flag;
position p;
statement S1,S2;
@@
* to = \(kmalloc@p\|kzalloc@p\)(size,flag);
if (to==NULL || ...) S1
if (copy_from_user(to, from, size) != 0)
S2
@script:python depends on org@
p << r.p;
@@
coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user")
@script:python depends on report@
p << r.p;
@@
coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user")
/// Find uses of standard freeing functons on values allocated using devm_
/// functions. Values allocated using the devm_functions are freed when
/// the device is detached, and thus the use of the standard freeing
/// function would cause a double free.
/// See Documentation/driver-model/devres.txt for more information.
///
/// A difficulty of detecting this problem is that the standard freeing
/// function might be called from a different function than the one
/// containing the allocation function. It is thus necessary to make the
/// connection between the allocation function and the freeing function.
/// Here this is done using the specific argument text, which is prone to
/// false positives. There is no rule for the request_region and
/// request_mem_region variants because this heuristic seems to be a bit
/// less reliable in these cases.
///
// Confidence: Moderate
// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/
// Comments:
// Options: -no_includes -include_headers
virtual org
virtual report
virtual context
@r depends on context || org || report@
expression x;
@@
(
x = devm_kzalloc(...)
|
x = devm_request_irq(...)
|
x = devm_ioremap(...)
|
x = devm_ioremap_nocache(...)
|
x = devm_ioport_map(...)
)
@pb@
expression r.x;
position p;
@@
(
* kfree@p(x)
|
* free_irq@p(x)
|
* iounmap@p(x)
|
* ioport_unmap@p(x)
)
@script:python depends on org@
p << pb.p;
@@
msg="WARNING: invalid free of devm_ allocated data"
coccilib.org.print_todo(p[0], msg)
@script:python depends on report@
p << pb.p;
@@
msg="WARNING: invalid free of devm_ allocated data"
coccilib.report.print_report(p[0], msg)
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
/// ///
// Confidence: Moderate // Confidence: Moderate
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
...@@ -23,7 +23,7 @@ position p1; ...@@ -23,7 +23,7 @@ position p1;
kfree@p1(E) kfree@p1(E)
@print expression@ @print expression@
constant char *c; constant char [] c;
expression free.E,E2; expression free.E,E2;
type T; type T;
position p; position p;
...@@ -36,6 +36,10 @@ identifier f; ...@@ -36,6 +36,10 @@ identifier f;
E@p == E2 E@p == E2
| |
E@p != E2 E@p != E2
|
E2 == E@p
|
E2 != E@p
| |
!E@p !E@p
| |
...@@ -113,5 +117,5 @@ p1 << free.p1; ...@@ -113,5 +117,5 @@ p1 << free.p1;
p2 << r.p2; p2 << r.p2;
@@ @@
msg = "reference preceded by free on line %s" % (p1[0].line) msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
coccilib.report.print_report(p2[0],msg) coccilib.report.print_report(p2[0],msg)
...@@ -2,16 +2,19 @@ ...@@ -2,16 +2,19 @@
/// is no point to call of_node_put on the final value. /// is no point to call of_node_put on the final value.
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@@ @depends on patch@
iterator name for_each_node_by_name; iterator name for_each_node_by_name;
expression np,E; expression np,E;
identifier l; identifier l;
...@@ -24,7 +27,7 @@ for_each_node_by_name(np,...) { ...@@ -24,7 +27,7 @@ for_each_node_by_name(np,...) {
... when != np = E ... when != np = E
- of_node_put(np); - of_node_put(np);
@@ @depends on patch@
iterator name for_each_node_by_type; iterator name for_each_node_by_type;
expression np,E; expression np,E;
identifier l; identifier l;
...@@ -37,7 +40,7 @@ for_each_node_by_type(np,...) { ...@@ -37,7 +40,7 @@ for_each_node_by_type(np,...) {
... when != np = E ... when != np = E
- of_node_put(np); - of_node_put(np);
@@ @depends on patch@
iterator name for_each_compatible_node; iterator name for_each_compatible_node;
expression np,E; expression np,E;
identifier l; identifier l;
...@@ -50,7 +53,7 @@ for_each_compatible_node(np,...) { ...@@ -50,7 +53,7 @@ for_each_compatible_node(np,...) {
... when != np = E ... when != np = E
- of_node_put(np); - of_node_put(np);
@@ @depends on patch@
iterator name for_each_matching_node; iterator name for_each_matching_node;
expression np,E; expression np,E;
identifier l; identifier l;
...@@ -62,3 +65,59 @@ for_each_matching_node(np,...) { ...@@ -62,3 +65,59 @@ for_each_matching_node(np,...) {
} }
... when != np = E ... when != np = E
- of_node_put(np); - of_node_put(np);
// ----------------------------------------------------------------------
@r depends on !patch forall@
//iterator name for_each_node_by_name;
//iterator name for_each_node_by_type;
//iterator name for_each_compatible_node;
//iterator name for_each_matching_node;
expression np,E;
identifier l;
position p1,p2;
@@
(
*for_each_node_by_name@p1(np,...)
{
... when != break;
when != goto l;
}
|
*for_each_node_by_type@p1(np,...)
{
... when != break;
when != goto l;
}
|
*for_each_compatible_node@p1(np,...)
{
... when != break;
when != goto l;
}
|
*for_each_matching_node@p1(np,...)
{
... when != break;
when != goto l;
}
)
... when != np = E
* of_node_put@p2(np);
@script:python depends on org@
p1 << r.p1;
p2 << r.p2;
@@
cocci.print_main("unneeded of_node_put",p2)
cocci.print_secs("iterator",p1)
@script:python depends on report@
p1 << r.p1;
p2 << r.p2;
@@
msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line)
coccilib.report.print_report(p2[0], msg)
/// Many iterators have the property that the first argument is always bound /// Many iterators have the property that the first argument is always bound
/// to a real list element, never NULL. False positives arise for some /// to a real list element, never NULL.
/// iterators that do not have this property, or in cases when the loop //# False positives arise for some iterators that do not have this property,
/// cursor is reassigned. The latter should only happen when the matched //# or in cases when the loop cursor is reassigned. The latter should only
/// code is on the way to a loop exit (break, goto, or return). //# happen when the matched code is on the way to a loop exit (break, goto,
//# or return).
/// ///
// Confidence: Moderate // Confidence: Moderate
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@@ @depends on patch@
iterator I; iterator I;
expression x,E,E1,E2; expression x,E,E1,E2;
statement S,S1,S2; statement S,S1,S2;
...@@ -55,4 +59,36 @@ I(x,...) { <... ...@@ -55,4 +59,36 @@ I(x,...) { <...
x != NULL x != NULL
+ ) + )
) )
...> } ...> }
\ No newline at end of file
@r depends on !patch exists@
iterator I;
expression x,E;
position p1,p2;
@@
*I@p1(x,...)
{ ... when != x = E
(
* x@p2 == NULL
|
* x@p2 != NULL
)
... when any
}
@script:python depends on org@
p1 << r.p1;
p2 << r.p2;
@@
cocci.print_main("iterator-bound variable",p1)
cocci.print_secs("useless NULL test",p2)
@script:python depends on report@
p1 << r.p1;
p2 << r.p2;
@@
msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
coccilib.report.print_report(p2[0], msg)
/// Find functions that refer to GFP_KERNEL but are called with locks held. /// Find functions that refer to GFP_KERNEL but are called with locks held.
/// The proposed change of converting the GFP_KERNEL is not necessarily the //# The proposed change of converting the GFP_KERNEL is not necessarily the
/// correct one. It may be desired to unlock the lock, or to not call the //# correct one. It may be desired to unlock the lock, or to not call the
/// function under the lock in the first place. //# function under the lock in the first place.
/// ///
// Confidence: Moderate // Confidence: Moderate
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@gfp exists@ @gfp exists@
identifier fn; identifier fn;
...@@ -32,28 +35,29 @@ fn(...) { ...@@ -32,28 +35,29 @@ fn(...) {
... when any ... when any
} }
@locked@ @locked exists@
identifier gfp.fn; identifier gfp.fn;
position p1,p2;
@@ @@
( (
read_lock_irq read_lock_irq@p1
| |
write_lock_irq write_lock_irq@p1
| |
read_lock_irqsave read_lock_irqsave@p1
| |
write_lock_irqsave write_lock_irqsave@p1
| |
spin_lock spin_lock@p1
| |
spin_trylock spin_trylock@p1
| |
spin_lock_irq spin_lock_irq@p1
| |
spin_lock_irqsave spin_lock_irqsave@p1
| |
local_irq_disable local_irq_disable@p1
) )
(...) (...)
... when != read_unlock_irq(...) ... when != read_unlock_irq(...)
...@@ -64,11 +68,38 @@ local_irq_disable ...@@ -64,11 +68,38 @@ local_irq_disable
when != spin_unlock_irq(...) when != spin_unlock_irq(...)
when != spin_unlock_irqrestore(...) when != spin_unlock_irqrestore(...)
when != local_irq_enable(...) when != local_irq_enable(...)
fn(...) fn@p2(...)
@depends on locked@ @depends on locked && patch@
position gfp.p; position gfp.p;
@@ @@
- GFP_KERNEL@p - GFP_KERNEL@p
+ GFP_ATOMIC + GFP_ATOMIC
@depends on locked && !patch@
position gfp.p;
@@
* GFP_KERNEL@p
@script:python depends on !patch && org@
p << gfp.p;
fn << gfp.fn;
p1 << locked.p1;
p2 << locked.p2;
@@
cocci.print_main("lock",p1)
cocci.print_secs("call",p2)
cocci.print_secs("GFP_KERNEL",p)
@script:python depends on !patch && report@
p << gfp.p;
fn << gfp.fn;
p1 << locked.p1;
p2 << locked.p2;
@@
msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line)
coccilib.report.print_report(p[0], msg)
/// Find nested lock+irqsave functions that use the same flags variables /// Find nested lock+irqsave functions that use the same flags variables
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
...@@ -12,7 +12,7 @@ virtual context ...@@ -12,7 +12,7 @@ virtual context
virtual org virtual org
virtual report virtual report
@r@ @r exists@
expression lock1,lock2,flags; expression lock1,lock2,flags;
position p1,p2; position p1,p2;
@@ @@
...@@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags) ...@@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags)
write_lock_irqsave@p2(lock2,flags) write_lock_irqsave@p2(lock2,flags)
) )
@d@ @d exists@
expression f <= r.flags; expression f <= r.flags;
expression lock1,lock2,flags; expression lock1,lock2,flags;
position r.p1, r.p2; position r.p1, r.p2;
...@@ -76,5 +76,5 @@ p1 << r.p1; ...@@ -76,5 +76,5 @@ p1 << r.p1;
p2 << r.p2; p2 << r.p2;
@@ @@
msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line) msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line)
coccilib.report.print_report(p2[0], msg) coccilib.report.print_report(p2[0], msg)
...@@ -6,13 +6,14 @@ ...@@ -6,13 +6,14 @@
/// function call that releases the lock. /// function call that releases the lock.
/// ///
// Confidence: Moderate // Confidence: Moderate
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual context
virtual org virtual org
virtual report virtual report
...@@ -57,7 +58,7 @@ position r; ...@@ -57,7 +58,7 @@ position r;
for(...;...;...) { <+... return@r ...; ...+> } for(...;...;...) { <+... return@r ...; ...+> }
@err@ @err exists@
expression E1; expression E1;
position prelocked.p; position prelocked.p;
position up != prelocked.p1; position up != prelocked.p1;
...@@ -65,14 +66,14 @@ position r!=looped.r; ...@@ -65,14 +66,14 @@ position r!=looped.r;
identifier lock,unlock; identifier lock,unlock;
@@ @@
lock(E1@p,...); *lock(E1@p,...);
<+... when != E1 <+... when != E1
if (...) { if (...) {
... when != E1 ... when != E1
return@r ...; * return@r ...;
} }
...+> ...+>
unlock@up(E1,...); *unlock@up(E1,...);
@script:python depends on org@ @script:python depends on org@
p << prelocked.p1; p << prelocked.p1;
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
/// initialization. /// initialization.
/// ///
// Confidence: Low // Confidence: Low
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
...@@ -49,5 +49,5 @@ pr << r.p; ...@@ -49,5 +49,5 @@ pr << r.p;
@@ @@
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)): 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)):
msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line) msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
coccilib.report.print_report(p0[0],msg) coccilib.report.print_report(p0[0],msg)
/// The various basic memory allocation functions don't return ERR_PTR /// The various basic memory allocation functions don't return ERR_PTR
/// ///
// Confidence: High // Confidence: High
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
// URL: http://coccinelle.lip6.fr/ // URL: http://coccinelle.lip6.fr/
// Comments: // Comments:
// Options: -no_includes -include_headers // Options: -no_includes -include_headers
virtual patch virtual patch
virtual context
virtual org
virtual report
@@ @depends on patch@
expression x,E; expression x,E;
@@ @@
...@@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache ...@@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache
... when != x = E ... when != x = E
- IS_ERR(x) - IS_ERR(x)
+ !x + !x
@r depends on !patch exists@
expression x,E;
position p1,p2;
@@
*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\)(...)
... when != x = E
* IS_ERR@p2(x)
@script:python depends on org@
p1 << r.p1;
p2 << r.p2;
@@
cocci.print_main("alloc call",p1)
cocci.print_secs("IS_ERR that should be NULL tests",p2)
@script:python depends on report@
p1 << r.p1;
p2 << r.p2;
@@
msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line)
coccilib.report.print_report(p2[0], msg)
...@@ -132,7 +132,28 @@ exuberant() ...@@ -132,7 +132,28 @@ exuberant()
--regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \
--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
--regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \
--regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \
--regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \
--regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \
--regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \
--regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \
--regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \
--regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \
--regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \
--regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \
--regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
--regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \
--regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
--regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \
--regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \
--regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \
--regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \
--regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
--regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
--regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
all_kconfigs | xargs $1 -a \ all_kconfigs | xargs $1 -a \
--langdef=kconfig --language-force=kconfig \ --langdef=kconfig --language-force=kconfig \
...@@ -146,6 +167,8 @@ exuberant() ...@@ -146,6 +167,8 @@ exuberant()
--langdef=dotconfig --language-force=dotconfig \ --langdef=dotconfig --language-force=dotconfig \
--regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'
# Remove structure forward declarations.
LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags
} }
emacs() emacs()
...@@ -154,7 +177,28 @@ emacs() ...@@ -154,7 +177,28 @@ emacs()
--regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \
--regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \
--regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \
--regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \
--regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \
--regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \
--regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \
--regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \
--regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \
--regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \
--regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \
--regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \
--regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
--regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \
--regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
--regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \
--regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \
--regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \
--regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \
--regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \
--regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
--regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
--regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
all_kconfigs | xargs $1 -a \ all_kconfigs | xargs $1 -a \
--regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment