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
This commit is contained in:
Коммит
408e057870
|
@ -102,9 +102,15 @@ or
|
|||
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
|
||||
following command may be used:
|
||||
|
||||
|
|
|
@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
|
|||
# FLAGS="-ignore_unknown_options -very_quiet"
|
||||
# OPTIONS=$*
|
||||
|
||||
# Workaround for Coccinelle < 0.2.3
|
||||
FLAGS="-I $srctree/include -very_quiet"
|
||||
shift $(( $# - 1 ))
|
||||
OPTIONS=$1
|
||||
if [ "$KBUILD_EXTMOD" = "" ] ; then
|
||||
# Workaround for Coccinelle < 0.2.3
|
||||
FLAGS="-I $srctree/include -very_quiet"
|
||||
shift $(( $# - 1 ))
|
||||
OPTIONS=$1
|
||||
else
|
||||
echo M= is not currently supported when C=1 or C=2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
ONLINE=0
|
||||
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
|
||||
|
||||
if [ ! -x "$SPATCH" ]; then
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/// 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)
|
|
@ -1,16 +1,19 @@
|
|||
/// Use kstrdup rather than duplicating its implementation
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
expression from,to;
|
||||
expression flag,E1,E2;
|
||||
statement S;
|
||||
|
@ -23,7 +26,7 @@ statement S;
|
|||
... when != \(from = E2 \| to = E2 \)
|
||||
- strcpy(to, from);
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
expression x,from,to;
|
||||
expression flag,E1,E2,E3;
|
||||
statement S;
|
||||
|
@ -37,3 +40,65 @@ statement S;
|
|||
if (to==NULL || ...) S
|
||||
... when != \(x = E3 \| from = E3 \| to = E3 \)
|
||||
- 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)
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
/// Use kmemdup rather than duplicating its implementation
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r1@
|
||||
expression from,to;
|
||||
|
@ -28,7 +31,7 @@ position p;
|
|||
... when != \( x = E1 \| from = E1 \)
|
||||
to = \(kmalloc@p\|kzalloc@p\)(x,flag);
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
expression from,to,size,flag;
|
||||
position p != {r1.p,r2.p};
|
||||
statement S;
|
||||
|
@ -38,3 +41,26 @@ statement S;
|
|||
+ to = kmemdup(from,size,flag);
|
||||
if (to==NULL || ...) S
|
||||
- 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")
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
/// 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
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
expression from,to,size,flag;
|
||||
position p;
|
||||
identifier l1,l2;
|
||||
@@
|
||||
|
||||
- to = \(kmalloc@p\|kzalloc@p\)(size,flag);
|
||||
- to = \(kmalloc\|kzalloc\)(size,flag);
|
||||
+ to = memdup_user(from,size);
|
||||
if (
|
||||
- to==NULL
|
||||
|
@ -33,3 +35,26 @@ identifier l1,l2;
|
|||
- -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")
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/// 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 @@
|
|||
//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
@ -23,7 +23,7 @@ position p1;
|
|||
kfree@p1(E)
|
||||
|
||||
@print expression@
|
||||
constant char *c;
|
||||
constant char [] c;
|
||||
expression free.E,E2;
|
||||
type T;
|
||||
position p;
|
||||
|
@ -36,6 +36,10 @@ identifier f;
|
|||
E@p == E2
|
||||
|
|
||||
E@p != E2
|
||||
|
|
||||
E2 == E@p
|
||||
|
|
||||
E2 != E@p
|
||||
|
|
||||
!E@p
|
||||
|
|
||||
|
@ -113,5 +117,5 @@ p1 << free.p1;
|
|||
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)
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
/// is no point to call of_node_put on the final value.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
iterator name for_each_node_by_name;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
|
@ -24,7 +27,7 @@ for_each_node_by_name(np,...) {
|
|||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
iterator name for_each_node_by_type;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
|
@ -37,7 +40,7 @@ for_each_node_by_type(np,...) {
|
|||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
iterator name for_each_compatible_node;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
|
@ -50,7 +53,7 @@ for_each_compatible_node(np,...) {
|
|||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
iterator name for_each_matching_node;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
|
@ -62,3 +65,59 @@ for_each_matching_node(np,...) {
|
|||
}
|
||||
... when != np = E
|
||||
- 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)
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
/// Many iterators have the property that the first argument is always bound
|
||||
/// to a real list element, never NULL. False positives arise for some
|
||||
/// iterators that do not have this property, or in cases when the loop
|
||||
/// cursor is reassigned. The latter should only happen when the matched
|
||||
/// code is on the way to a loop exit (break, goto, or return).
|
||||
/// to a real list element, never NULL.
|
||||
//# False positives arise for some iterators that do not have this property,
|
||||
//# or in cases when the loop cursor is reassigned. The latter should only
|
||||
//# happen when the matched code is on the way to a loop exit (break, goto,
|
||||
//# or return).
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
iterator I;
|
||||
expression x,E,E1,E2;
|
||||
statement S,S1,S2;
|
||||
|
@ -55,4 +59,36 @@ I(x,...) { <...
|
|||
x != NULL
|
||||
+ )
|
||||
)
|
||||
...> }
|
||||
...> }
|
||||
|
||||
@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)
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
/// 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
|
||||
/// correct one. It may be desired to unlock the lock, or to not call the
|
||||
/// function under the lock in the first place.
|
||||
//# 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
|
||||
//# function under the lock in the first place.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@gfp exists@
|
||||
identifier fn;
|
||||
|
@ -32,28 +35,29 @@ fn(...) {
|
|||
... when any
|
||||
}
|
||||
|
||||
@locked@
|
||||
@locked exists@
|
||||
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(...)
|
||||
|
@ -64,11 +68,38 @@ local_irq_disable
|
|||
when != spin_unlock_irq(...)
|
||||
when != spin_unlock_irqrestore(...)
|
||||
when != local_irq_enable(...)
|
||||
fn(...)
|
||||
fn@p2(...)
|
||||
|
||||
@depends on locked@
|
||||
@depends on locked && patch@
|
||||
position gfp.p;
|
||||
@@
|
||||
|
||||
- GFP_KERNEL@p
|
||||
+ 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)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/// Find nested lock+irqsave functions that use the same flags variables
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
@ -12,7 +12,7 @@ virtual context
|
|||
virtual org
|
||||
virtual report
|
||||
|
||||
@r@
|
||||
@r exists@
|
||||
expression lock1,lock2,flags;
|
||||
position p1,p2;
|
||||
@@
|
||||
|
@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags)
|
|||
write_lock_irqsave@p2(lock2,flags)
|
||||
)
|
||||
|
||||
@d@
|
||||
@d exists@
|
||||
expression f <= r.flags;
|
||||
expression lock1,lock2,flags;
|
||||
position r.p1, r.p2;
|
||||
|
@ -76,5 +76,5 @@ p1 << r.p1;
|
|||
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)
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
/// function call that releases the lock.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
|
@ -57,7 +58,7 @@ position r;
|
|||
|
||||
for(...;...;...) { <+... return@r ...; ...+> }
|
||||
|
||||
@err@
|
||||
@err exists@
|
||||
expression E1;
|
||||
position prelocked.p;
|
||||
position up != prelocked.p1;
|
||||
|
@ -65,14 +66,14 @@ position r!=looped.r;
|
|||
identifier lock,unlock;
|
||||
@@
|
||||
|
||||
lock(E1@p,...);
|
||||
*lock(E1@p,...);
|
||||
<+... when != E1
|
||||
if (...) {
|
||||
... when != E1
|
||||
return@r ...;
|
||||
* return@r ...;
|
||||
}
|
||||
...+>
|
||||
unlock@up(E1,...);
|
||||
*unlock@up(E1,...);
|
||||
|
||||
@script:python depends on org@
|
||||
p << prelocked.p1;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
/// initialization.
|
||||
///
|
||||
// Confidence: Low
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
|
||||
// Options: -no_includes -include_headers
|
||||
|
@ -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)):
|
||||
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)
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
/// The various basic memory allocation functions don't return ERR_PTR
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||
// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@@
|
||||
@depends on patch@
|
||||
expression x,E;
|
||||
@@
|
||||
|
||||
|
@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache
|
|||
... when != x = E
|
||||
- IS_ERR(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()
|
|||
--regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \
|
||||
--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\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 \
|
||||
--langdef=kconfig --language-force=kconfig \
|
||||
|
@ -146,6 +167,8 @@ exuberant()
|
|||
--langdef=dotconfig --language-force=dotconfig \
|
||||
--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()
|
||||
|
@ -154,7 +177,28 @@ emacs()
|
|||
--regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \
|
||||
--regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\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 \
|
||||
--regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
|
||||
|
|
Загрузка…
Ссылка в новой задаче