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:
# 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
--- /dev/null
+/// 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
///
// 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;
... when != \(from = E2 \| to = E2 \)
- strcpy(to, from);
-@@
+@depends on patch@
expression x,from,to;
expression flag,E1,E2,E3;
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)
/// 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;
... 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;
+ 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")
-/// 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
- -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")
--- /dev/null
+/// 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)
+
//# 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
kfree@p1(E)
@print expression@
-constant char *c;
+constant char [] c;
expression free.E,E2;
type T;
position p;
|
E@p != E2
|
+ E2 == E@p
+|
+ E2 != E@p
+|
!E@p
|
E@p || ...
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)
/// 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;
... when != np = E
- of_node_put(np);
-@@
+@depends on patch@
iterator name for_each_node_by_type;
expression np,E;
identifier l;
... when != np = E
- of_node_put(np);
-@@
+@depends on patch@
iterator name for_each_compatible_node;
expression np,E;
identifier l;
... when != np = E
- of_node_put(np);
-@@
+@depends on patch@
iterator name for_each_matching_node;
expression np,E;
identifier l;
}
... 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)
/// 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;
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.
-/// 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;
... 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(...)
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)
/// 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
virtual org
virtual report
-@r@
+@r exists@
expression lock1,lock2,flags;
position p1,p2;
@@
write_lock_irqsave@p2(lock2,flags)
)
-@d@
+@d exists@
expression f <= r.flags;
expression lock1,lock2,flags;
position r.p1, 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)
/// 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
for(...;...;...) { <+... return@r ...; ...+> }
-@err@
+@err exists@
expression E1;
position prelocked.p;
position up != prelocked.p1;
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;
/// 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
@@
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)
/// 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;
@@
... 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)
--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 \
--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()
--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/'