mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 11:18:43 +00:00
tools: add coccinelle spatches
Add some Coccinelle semantic patches we can use to automatically refactor code in the future. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
aa406bbcc8
commit
25af5f0d79
101
tools/coccinelle/alloc_cast.cocci
Normal file
101
tools/coccinelle/alloc_cast.cocci
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/// Remove casting the values returned by memory allocation functions
|
||||||
|
/// like XMALLOC and XCALLOC.
|
||||||
|
///
|
||||||
|
// This makes an effort to find cases of casting of values returned by #
|
||||||
|
// XMALLOC and XCALLOC and removes the casting as it is not required. The
|
||||||
|
// result in the patch case may need some reformatting.
|
||||||
|
//
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2014 Himangi Saraogi GPLv2.
|
||||||
|
// Copyright: (C) 2017 Himanshu Jha GPLv2.
|
||||||
|
// Copyright: (C) 2019 Quentin Young GPLv2.
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual patch
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@initialize:python@
|
||||||
|
@@
|
||||||
|
import re
|
||||||
|
pattern = '__'
|
||||||
|
m = re.compile(pattern)
|
||||||
|
|
||||||
|
@r1 depends on context || patch@
|
||||||
|
type T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(T *)
|
||||||
|
\(XMALLOC\|XCALLOC\)(...)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For context mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python depends on context@
|
||||||
|
t << r1.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if m.search(t) != None:
|
||||||
|
cocci.include_match(False)
|
||||||
|
|
||||||
|
@depends on context && r1@
|
||||||
|
type r1.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* (T *)
|
||||||
|
\(XMALLOC\|XCALLOC\)(...)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python depends on patch@
|
||||||
|
t << r1.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if m.search(t) != None:
|
||||||
|
cocci.include_match(False)
|
||||||
|
|
||||||
|
@depends on patch && r1@
|
||||||
|
type r1.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
- (T *)
|
||||||
|
\(XMALLOC\|XCALLOC\)(...)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For org and report mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@r2 depends on org || report@
|
||||||
|
type T;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(T@p *)
|
||||||
|
\(XMALLOC\|XCALLOC\)(...)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r2.p;
|
||||||
|
t << r2.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if m.search(t) != None:
|
||||||
|
cocci.include_match(False)
|
||||||
|
else:
|
||||||
|
coccilib.org.print_safe_todo(p[0], t)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r2.p;
|
||||||
|
t << r2.T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if m.search(t) != None:
|
||||||
|
cocci.include_match(False)
|
||||||
|
else:
|
||||||
|
msg="WARNING: casting value returned by memory allocation function to (%s *) is useless." % (t)
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
83
tools/coccinelle/array_size.cocci
Normal file
83
tools/coccinelle/array_size.cocci
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/// Use array_size instead of dividing sizeof array with sizeof an element
|
||||||
|
///
|
||||||
|
//# This makes an effort to find cases where array_size can be used such as
|
||||||
|
//# where there is a division of sizeof the array by the sizeof its first
|
||||||
|
//# element or by any indexed element or the element type. It replaces the
|
||||||
|
//# division of the two sizeofs by array_size.
|
||||||
|
//
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For context mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on context@
|
||||||
|
type T;
|
||||||
|
T[] E;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
* (sizeof(E)/sizeof(*E))
|
||||||
|
|
|
||||||
|
* (sizeof(E)/sizeof(E[...]))
|
||||||
|
|
|
||||||
|
* (sizeof(E)/sizeof(T))
|
||||||
|
)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
type T;
|
||||||
|
T[] E;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
- (sizeof(E)/sizeof(*E))
|
||||||
|
+ array_size(E)
|
||||||
|
|
|
||||||
|
- (sizeof(E)/sizeof(E[...]))
|
||||||
|
+ array_size(E)
|
||||||
|
|
|
||||||
|
- (sizeof(E)/sizeof(T))
|
||||||
|
+ array_size(E)
|
||||||
|
)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For org and report mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@r depends on (org || report)@
|
||||||
|
type T;
|
||||||
|
T[] E;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
(sizeof(E)@p /sizeof(*E))
|
||||||
|
|
|
||||||
|
(sizeof(E)@p /sizeof(E[...]))
|
||||||
|
|
|
||||||
|
(sizeof(E)@p /sizeof(T))
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING should use array_size")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg="WARNING: Use array_size"
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
||||||
|
|
76
tools/coccinelle/badty.cocci
Normal file
76
tools/coccinelle/badty.cocci
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
|
||||||
|
///
|
||||||
|
//# This makes an effort to find cases where the argument to sizeof is wrong
|
||||||
|
//# in memory allocation functions by checking the type of the allocated memory
|
||||||
|
//# when it is a double pointer and ensuring the sizeof argument takes a pointer
|
||||||
|
//# to the the memory being allocated. There are false positives in cases the
|
||||||
|
//# sizeof argument is not used in constructing the return value. The result
|
||||||
|
//# may need some reformatting.
|
||||||
|
//
|
||||||
|
// Confidence: Moderate
|
||||||
|
// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
|
||||||
|
// Comments:
|
||||||
|
// Options:
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For context mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on context disable sizeof_type_expr@
|
||||||
|
type T;
|
||||||
|
T **x;
|
||||||
|
@@
|
||||||
|
|
||||||
|
x =
|
||||||
|
<+...sizeof(
|
||||||
|
* T
|
||||||
|
)...+>
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on patch disable sizeof_type_expr@
|
||||||
|
type T;
|
||||||
|
T **x;
|
||||||
|
@@
|
||||||
|
|
||||||
|
x =
|
||||||
|
<+...sizeof(
|
||||||
|
- T
|
||||||
|
+ *x
|
||||||
|
)...+>
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For org and report mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@r depends on (org || report) disable sizeof_type_expr@
|
||||||
|
type T;
|
||||||
|
T **x;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
x =
|
||||||
|
<+...sizeof(
|
||||||
|
T@p
|
||||||
|
)...+>
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg="WARNING: Use correct pointer type argument for sizeof"
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
||||||
|
|
238
tools/coccinelle/badzero.cocci
Normal file
238
tools/coccinelle/badzero.cocci
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/// Compare pointer-typed values to NULL rather than 0
|
||||||
|
///
|
||||||
|
//# This makes an effort to choose between !x and x == NULL. !x is used
|
||||||
|
//# if it has previously been used with the function used to initialize x.
|
||||||
|
//# This relies on type information. More type information can be obtained
|
||||||
|
//# using the option -all_includes and the option -I to specify an
|
||||||
|
//# include path.
|
||||||
|
//
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||||
|
// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Requires: 1.0.0
|
||||||
|
// Options:
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@initialize:ocaml@
|
||||||
|
@@
|
||||||
|
let negtable = Hashtbl.create 101
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression *E;
|
||||||
|
identifier f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
(E = f(...)) ==
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
|
|
||||||
|
(E = f(...)) !=
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
|
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
== (E = f(...))
|
||||||
|
|
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
!= (E = f(...))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@t1 depends on !patch@
|
||||||
|
expression *E;
|
||||||
|
identifier f;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
(E = f(...)) ==
|
||||||
|
* 0@p
|
||||||
|
|
|
||||||
|
(E = f(...)) !=
|
||||||
|
* 0@p
|
||||||
|
|
|
||||||
|
* 0@p
|
||||||
|
== (E = f(...))
|
||||||
|
|
|
||||||
|
* 0@p
|
||||||
|
!= (E = f(...))
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << t1.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << t1.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|
||||||
|
|
||||||
|
// Tests of returned values
|
||||||
|
|
||||||
|
@s@
|
||||||
|
identifier f;
|
||||||
|
expression E,E1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = f(...)
|
||||||
|
... when != E = E1
|
||||||
|
!E
|
||||||
|
|
||||||
|
@script:ocaml depends on s@
|
||||||
|
f << s.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
try let _ = Hashtbl.find negtable f in ()
|
||||||
|
with Not_found -> Hashtbl.add negtable f ()
|
||||||
|
|
||||||
|
@ r disable is_zero,isnt_zero exists @
|
||||||
|
expression *E;
|
||||||
|
identifier f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = f(...)
|
||||||
|
...
|
||||||
|
(E == 0
|
||||||
|
|E != 0
|
||||||
|
|0 == E
|
||||||
|
|0 != E
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:ocaml@
|
||||||
|
f << r.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
try let _ = Hashtbl.find negtable f in ()
|
||||||
|
with Not_found -> include_match false
|
||||||
|
|
||||||
|
// This rule may lead to inconsistent path problems, if E is defined in two
|
||||||
|
// places
|
||||||
|
@ depends on patch disable is_zero,isnt_zero @
|
||||||
|
expression *E;
|
||||||
|
expression E1;
|
||||||
|
identifier r.f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = f(...)
|
||||||
|
<...
|
||||||
|
(
|
||||||
|
- E == 0
|
||||||
|
+ !E
|
||||||
|
|
|
||||||
|
- E != 0
|
||||||
|
+ E
|
||||||
|
|
|
||||||
|
- 0 == E
|
||||||
|
+ !E
|
||||||
|
|
|
||||||
|
- 0 != E
|
||||||
|
+ E
|
||||||
|
)
|
||||||
|
...>
|
||||||
|
?E = E1
|
||||||
|
|
||||||
|
@t2 depends on !patch disable is_zero,isnt_zero @
|
||||||
|
expression *E;
|
||||||
|
expression E1;
|
||||||
|
identifier r.f;
|
||||||
|
position p1;
|
||||||
|
position p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
E = f(...)
|
||||||
|
<...
|
||||||
|
(
|
||||||
|
* E == 0@p1
|
||||||
|
|
|
||||||
|
* E != 0@p2
|
||||||
|
|
|
||||||
|
* 0@p1 == E
|
||||||
|
|
|
||||||
|
* 0@p1 != E
|
||||||
|
)
|
||||||
|
...>
|
||||||
|
?E = E1
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << t2.p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0, suggest !E")
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << t2.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << t2.p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING comparing pointer to 0, suggest !E")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << t2.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|
||||||
|
|
||||||
|
@ depends on patch disable is_zero,isnt_zero @
|
||||||
|
expression *E;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
E ==
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
|
|
||||||
|
E !=
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
|
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
== E
|
||||||
|
|
|
||||||
|
- 0
|
||||||
|
+ NULL
|
||||||
|
!= E
|
||||||
|
)
|
||||||
|
|
||||||
|
@ t3 depends on !patch disable is_zero,isnt_zero @
|
||||||
|
expression *E;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* E == 0@p
|
||||||
|
|
|
||||||
|
* E != 0@p
|
||||||
|
|
|
||||||
|
* 0@p == E
|
||||||
|
|
|
||||||
|
* 0@p != E
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << t3.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << t3.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|
90
tools/coccinelle/boolconv.cocci
Normal file
90
tools/coccinelle/boolconv.cocci
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/// Remove unneeded conversion to bool
|
||||||
|
///
|
||||||
|
//# Relational and logical operators evaluate to bool,
|
||||||
|
//# explicit conversion is overly verbose and unneeded.
|
||||||
|
//
|
||||||
|
// Copyright: (C) 2016 Andrew F. Davis <afd@ti.com> GPLv2.
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression A, B;
|
||||||
|
symbol true, false;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
A == B
|
||||||
|
|
|
||||||
|
A != B
|
||||||
|
|
|
||||||
|
A > B
|
||||||
|
|
|
||||||
|
A < B
|
||||||
|
|
|
||||||
|
A >= B
|
||||||
|
|
|
||||||
|
A <= B
|
||||||
|
|
|
||||||
|
A && B
|
||||||
|
|
|
||||||
|
A || B
|
||||||
|
)
|
||||||
|
- ? true : false
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For context mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@r depends on !patch@
|
||||||
|
expression A, B;
|
||||||
|
symbol true, false;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
A == B
|
||||||
|
|
|
||||||
|
A != B
|
||||||
|
|
|
||||||
|
A > B
|
||||||
|
|
|
||||||
|
A < B
|
||||||
|
|
|
||||||
|
A >= B
|
||||||
|
|
|
||||||
|
A <= B
|
||||||
|
|
|
||||||
|
A && B
|
||||||
|
|
|
||||||
|
A || B
|
||||||
|
)
|
||||||
|
* ? true : false@p
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For org mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python depends on r&&org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: conversion to bool not needed here"
|
||||||
|
coccilib.org.print_todo(p[0], msg)
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For report mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@script:python depends on r&&report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: conversion to bool not needed here"
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
194
tools/coccinelle/boolinit.cocci
Normal file
194
tools/coccinelle/boolinit.cocci
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/// Bool initializations should use true and false. Bool tests don't need
|
||||||
|
/// comparisons. Based on contributions from Joe Perches, Rusty Russell
|
||||||
|
/// and Bruce W Allan.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||||
|
// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Options: --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@boolok@
|
||||||
|
symbol true,false;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
true
|
||||||
|
|
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
bool t;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
- t == true
|
||||||
|
+ t
|
||||||
|
|
|
||||||
|
- true == t
|
||||||
|
+ t
|
||||||
|
|
|
||||||
|
- t != true
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- true != t
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- t == false
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- false == t
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- t != false
|
||||||
|
+ t
|
||||||
|
|
|
||||||
|
- false != t
|
||||||
|
+ t
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on patch disable is_zero, isnt_zero@
|
||||||
|
bool t;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
- t == 1
|
||||||
|
+ t
|
||||||
|
|
|
||||||
|
- t != 1
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- t == 0
|
||||||
|
+ !t
|
||||||
|
|
|
||||||
|
- t != 0
|
||||||
|
+ t
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on patch && boolok@
|
||||||
|
bool b;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
b =
|
||||||
|
- 0
|
||||||
|
+ false
|
||||||
|
|
|
||||||
|
b =
|
||||||
|
- 1
|
||||||
|
+ true
|
||||||
|
)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
@r1 depends on !patch@
|
||||||
|
bool t;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* t@p == true
|
||||||
|
|
|
||||||
|
* true == t@p
|
||||||
|
|
|
||||||
|
* t@p != true
|
||||||
|
|
|
||||||
|
* true != t@p
|
||||||
|
|
|
||||||
|
* t@p == false
|
||||||
|
|
|
||||||
|
* false == t@p
|
||||||
|
|
|
||||||
|
* t@p != false
|
||||||
|
|
|
||||||
|
* false != t@p
|
||||||
|
)
|
||||||
|
|
||||||
|
@r2 depends on !patch disable is_zero, isnt_zero@
|
||||||
|
bool t;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* t@p == 1
|
||||||
|
|
|
||||||
|
* t@p != 1
|
||||||
|
|
|
||||||
|
* t@p == 0
|
||||||
|
|
|
||||||
|
* t@p != 0
|
||||||
|
)
|
||||||
|
|
||||||
|
@r3 depends on !patch && boolok@
|
||||||
|
bool b;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
*b@p1 = 0
|
||||||
|
|
|
||||||
|
*b@p1 = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
@r4 depends on !patch@
|
||||||
|
bool b;
|
||||||
|
position p2;
|
||||||
|
identifier i;
|
||||||
|
constant c != {0,1};
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
b = i
|
||||||
|
|
|
||||||
|
*b@p2 = c
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r1.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("WARNING: Comparison to bool",p)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r2.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("WARNING: Comparison of 0/1 to bool variable",p)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p1 << r3.p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("WARNING: Assignment of 0/1 to bool variable",p1)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p2 << r4.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("ERROR: Assignment of non-0/1 constant to bool variable",p2)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r1.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],"WARNING: Comparison to bool")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r2.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],"WARNING: Comparison of 0/1 to bool variable")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p1 << r3.p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p1[0],"WARNING: Assignment of 0/1 to bool variable")
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p2 << r4.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p2[0],"ERROR: Assignment of non-0/1 constant to bool variable")
|
59
tools/coccinelle/boolreturn.cocci
Normal file
59
tools/coccinelle/boolreturn.cocci
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/// Return statements in functions returning bool should use
|
||||||
|
/// true/false instead of 1/0.
|
||||||
|
//
|
||||||
|
// Confidence: High
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
|
||||||
|
@r1 depends on patch@
|
||||||
|
identifier fn;
|
||||||
|
typedef bool;
|
||||||
|
symbol false;
|
||||||
|
symbol true;
|
||||||
|
@@
|
||||||
|
|
||||||
|
bool fn ( ... )
|
||||||
|
{
|
||||||
|
<...
|
||||||
|
return
|
||||||
|
(
|
||||||
|
- 0
|
||||||
|
+ false
|
||||||
|
|
|
||||||
|
- 1
|
||||||
|
+ true
|
||||||
|
)
|
||||||
|
;
|
||||||
|
...>
|
||||||
|
}
|
||||||
|
|
||||||
|
@r2 depends on report || context@
|
||||||
|
identifier fn;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
bool fn ( ... )
|
||||||
|
{
|
||||||
|
<...
|
||||||
|
return
|
||||||
|
(
|
||||||
|
* 0@p
|
||||||
|
|
|
||||||
|
* 1@p
|
||||||
|
)
|
||||||
|
;
|
||||||
|
...>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r2.p;
|
||||||
|
fn << r2.fn;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: return of 0/1 in function '%s' with return type bool" % fn
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
64
tools/coccinelle/cond_no_effect.cocci
Normal file
64
tools/coccinelle/cond_no_effect.cocci
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
///Find conditions where if and else branch are functionally
|
||||||
|
// identical.
|
||||||
|
//
|
||||||
|
// There can be false positives in cases where the positional
|
||||||
|
// information is used (as with lockdep) or where the identity
|
||||||
|
// is a placeholder for not yet handled cases.
|
||||||
|
// Unfortunately there also seems to be a tendency to use
|
||||||
|
// the last if else/else as a "default behavior" - which some
|
||||||
|
// might consider a legitimate coding pattern. From discussion
|
||||||
|
// on kernelnewbies though it seems that this is not really an
|
||||||
|
// accepted pattern and if at all it would need to be commented
|
||||||
|
//
|
||||||
|
// In the Linux kernel it does not seem to actually report
|
||||||
|
// false positives except for those that were documented as
|
||||||
|
// being intentional.
|
||||||
|
// the two known cases are:
|
||||||
|
// arch/sh/kernel/traps_64.c:read_opcode()
|
||||||
|
// } else if ((pc & 1) == 0) {
|
||||||
|
// /* SHcompact */
|
||||||
|
// /* TODO : provide handling for this. We don't really support
|
||||||
|
// user-mode SHcompact yet, and for a kernel fault, this would
|
||||||
|
// have to come from a module built for SHcompact. */
|
||||||
|
// return -EFAULT;
|
||||||
|
// } else {
|
||||||
|
// /* misaligned */
|
||||||
|
// return -EFAULT;
|
||||||
|
// }
|
||||||
|
// fs/kernfs/file.c:kernfs_fop_open()
|
||||||
|
// * Both paths of the branch look the same. They're supposed to
|
||||||
|
// * look that way and give @of->mutex different static lockdep keys.
|
||||||
|
// */
|
||||||
|
// if (has_mmap)
|
||||||
|
// mutex_init(&of->mutex);
|
||||||
|
// else
|
||||||
|
// mutex_init(&of->mutex);
|
||||||
|
//
|
||||||
|
// All other cases look like bugs or at least lack of documentation
|
||||||
|
//
|
||||||
|
// Confidence: Moderate
|
||||||
|
// Copyright: (C) 2016 Nicholas Mc Guire, OSADL. GPLv2.
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@cond@
|
||||||
|
statement S1;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* if@p (...) S1 else S1
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << cond.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("WARNING: possible condition with no effect (if == else)",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << cond.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],"WARNING: possible condition with no effect (if == else)")
|
282
tools/coccinelle/deref_null.cocci
Normal file
282
tools/coccinelle/deref_null.cocci
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
///
|
||||||
|
/// A variable is dereferenced under a NULL test.
|
||||||
|
/// Even though it is known 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 org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
// The following two rules are separate, because both can match a single
|
||||||
|
// expression in different ways
|
||||||
|
@pr1 expression@
|
||||||
|
expression E;
|
||||||
|
identifier f;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(E != NULL && ...) ? <+...E->f@p1...+> : ...
|
||||||
|
|
||||||
|
@pr2 expression@
|
||||||
|
expression E;
|
||||||
|
identifier f;
|
||||||
|
position p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
(E != NULL) && ... && <+...E->f@p2...+>
|
||||||
|
|
|
||||||
|
(E == NULL) || ... || <+...E->f@p2...+>
|
||||||
|
|
|
||||||
|
sizeof(<+...E->f@p2...+>)
|
||||||
|
)
|
||||||
|
|
||||||
|
@ifm@
|
||||||
|
expression *E;
|
||||||
|
statement S1,S2;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if@p1 ((E == NULL && ...) || ...) S1 else S2
|
||||||
|
|
||||||
|
// For org and report modes
|
||||||
|
|
||||||
|
@r depends on !context && (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 && !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 && 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 && (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 && !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 && 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 && !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".
|
||||||
|
|
||||||
|
@pr11 depends on context && !org && !report expression@
|
||||||
|
expression E;
|
||||||
|
identifier f;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(E != NULL && ...) ? <+...E->f@p1...+> : ...
|
||||||
|
|
||||||
|
@pr12 depends on context && !org && !report expression@
|
||||||
|
expression E;
|
||||||
|
identifier f;
|
||||||
|
position p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
(E != NULL) && ... && <+...E->f@p2...+>
|
||||||
|
|
|
||||||
|
(E == NULL) || ... || <+...E->f@p2...+>
|
||||||
|
|
|
||||||
|
sizeof(<+...E->f@p2...+>)
|
||||||
|
)
|
||||||
|
|
||||||
|
@ifm1 depends on context && !org && !report@
|
||||||
|
expression *E;
|
||||||
|
statement S1,S2;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if@p1 ((E == NULL && ...) || ...) S1 else S2
|
||||||
|
|
||||||
|
@depends on context && !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
|
92
tools/coccinelle/double_lock.cocci
Normal file
92
tools/coccinelle/double_lock.cocci
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/// Find double locks. False positives may occur when some paths cannot
|
||||||
|
/// occur at execution, due to the values of variables, and when there is
|
||||||
|
/// an intervening 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.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@locked@
|
||||||
|
position p1;
|
||||||
|
expression E1;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
mutex_lock@p1
|
||||||
|
|
|
||||||
|
mutex_trylock@p1
|
||||||
|
|
|
||||||
|
spin_lock@p1
|
||||||
|
|
|
||||||
|
spin_trylock@p1
|
||||||
|
|
|
||||||
|
read_lock@p1
|
||||||
|
|
|
||||||
|
read_trylock@p1
|
||||||
|
|
|
||||||
|
write_lock@p1
|
||||||
|
|
|
||||||
|
write_trylock@p1
|
||||||
|
) (E1@p,...);
|
||||||
|
|
||||||
|
@balanced@
|
||||||
|
position p1 != locked.p1;
|
||||||
|
position locked.p;
|
||||||
|
identifier lock,unlock;
|
||||||
|
expression x <= locked.E1;
|
||||||
|
expression E,locked.E1;
|
||||||
|
expression E2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
if (E) {
|
||||||
|
<+... when != E1
|
||||||
|
lock(E1@p,...)
|
||||||
|
...+>
|
||||||
|
}
|
||||||
|
... when != E1
|
||||||
|
when != \(x = E2\|&x\)
|
||||||
|
when forall
|
||||||
|
if (E) {
|
||||||
|
<+... when != E1
|
||||||
|
unlock@p1(E1,...)
|
||||||
|
...+>
|
||||||
|
}
|
||||||
|
|
||||||
|
@r depends on !balanced exists@
|
||||||
|
expression x <= locked.E1;
|
||||||
|
expression locked.E1;
|
||||||
|
expression E2;
|
||||||
|
identifier lock;
|
||||||
|
position locked.p,p1,p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
lock@p1 (E1@p,...);
|
||||||
|
... when != E1
|
||||||
|
when != \(x = E2\|&x\)
|
||||||
|
lock@p2 (E1,...);
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p1 << r.p1;
|
||||||
|
p2 << r.p2;
|
||||||
|
lock << r.lock;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main(lock,p1)
|
||||||
|
cocci.print_secs("second lock",p2)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p1 << r.p1;
|
||||||
|
p2 << r.p2;
|
||||||
|
lock << r.lock;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "second lock on line %s" % (p2[0].line)
|
||||||
|
coccilib.report.print_report(p1[0],msg)
|
54
tools/coccinelle/doublebitand.cocci
Normal file
54
tools/coccinelle/doublebitand.cocci
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/// Find bit operations that include the same argument more than once
|
||||||
|
//# One source of false positives is when the argument performs a side
|
||||||
|
//# effect. Another source of false positives is when a neutral value
|
||||||
|
//# such as 0 for | is used to indicate no information, to maintain the
|
||||||
|
//# same structure as other similar expressions
|
||||||
|
///
|
||||||
|
// 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:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r expression@
|
||||||
|
expression E;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
* E@p
|
||||||
|
& ... & E
|
||||||
|
|
|
||||||
|
* E@p
|
||||||
|
| ... | E
|
||||||
|
|
|
||||||
|
* E@p
|
||||||
|
& ... & !E
|
||||||
|
|
|
||||||
|
* E@p
|
||||||
|
| ... | !E
|
||||||
|
|
|
||||||
|
* !E@p
|
||||||
|
& ... & E
|
||||||
|
|
|
||||||
|
* !E@p
|
||||||
|
| ... | E
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("duplicated argument to & or |",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],"duplicated argument to & or |")
|
53
tools/coccinelle/doubleinit.cocci
Normal file
53
tools/coccinelle/doubleinit.cocci
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/// Find duplicate field initializations. This has a high rate of false
|
||||||
|
/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
|
||||||
|
/// initialization.
|
||||||
|
///
|
||||||
|
// Confidence: Low
|
||||||
|
// 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
|
||||||
|
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r@
|
||||||
|
identifier I, s, fld;
|
||||||
|
position p0,p;
|
||||||
|
expression E;
|
||||||
|
@@
|
||||||
|
|
||||||
|
struct I s =@p0 { ..., .fld@p = E, ...};
|
||||||
|
|
||||||
|
@s@
|
||||||
|
identifier I, s, r.fld;
|
||||||
|
position r.p0,p;
|
||||||
|
expression E;
|
||||||
|
@@
|
||||||
|
|
||||||
|
struct I s =@p0 { ..., .fld@p = E, ...};
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p0 << r.p0;
|
||||||
|
fld << r.fld;
|
||||||
|
ps << s.p;
|
||||||
|
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)):
|
||||||
|
cocci.print_main(fld,p0)
|
||||||
|
cocci.print_secs("s",ps)
|
||||||
|
cocci.print_secs("r",pr)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p0 << r.p0;
|
||||||
|
fld << r.fld;
|
||||||
|
ps << s.p;
|
||||||
|
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 line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
|
||||||
|
coccilib.report.print_report(p0[0],msg)
|
58
tools/coccinelle/doubletest.cocci
Normal file
58
tools/coccinelle/doubletest.cocci
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/// Find &&/|| operations that include the same argument more than once
|
||||||
|
//# A common source of false positives is when the expression, or
|
||||||
|
//# another expresssion in the same && or || operation, performs a
|
||||||
|
//# side effect.
|
||||||
|
///
|
||||||
|
// 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:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r expression@
|
||||||
|
expression E;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
E@p || ... || E
|
||||||
|
|
|
||||||
|
E@p && ... && E
|
||||||
|
)
|
||||||
|
|
||||||
|
@bad@
|
||||||
|
expression r.E,e1,e2,fn;
|
||||||
|
position r.p;
|
||||||
|
assignment operator op;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
E@p
|
||||||
|
&
|
||||||
|
<+... \(fn(...)\|e1 op e2\|e1++\|e1--\|++e1\|--e1\) ...+>
|
||||||
|
)
|
||||||
|
|
||||||
|
@depends on context && !bad@
|
||||||
|
expression r.E;
|
||||||
|
position r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
*E@p
|
||||||
|
|
||||||
|
@script:python depends on org && !bad@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("duplicated argument to && or ||",p)
|
||||||
|
|
||||||
|
@script:python depends on report && !bad@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
coccilib.report.print_report(p[0],"duplicated argument to && or ||")
|
34
tools/coccinelle/ifaddr.cocci
Normal file
34
tools/coccinelle/ifaddr.cocci
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/// The address of a variable or field is likely always to be non-zero.
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// 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 org
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
|
||||||
|
@r@
|
||||||
|
expression x;
|
||||||
|
statement S1,S2;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
*if@p (&x)
|
||||||
|
S1 else S2
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("test of a variable/field address",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "ERROR: test of a variable/field address"
|
||||||
|
coccilib.report.print_report(p[0],msg)
|
15
tools/coccinelle/ifnullxfree.cocci
Normal file
15
tools/coccinelle/ifnullxfree.cocci
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/// NULL check before some freeing functions is not needed.
|
||||||
|
///
|
||||||
|
// Copyright: (C) 2014 Fabian Frederick. GPLv2.
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
// Comments: -
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
@r2 depends on patch@
|
||||||
|
expression E;
|
||||||
|
expression Y;
|
||||||
|
@@
|
||||||
|
- if (E != NULL)
|
||||||
|
XFREE(Y, E);
|
94
tools/coccinelle/itnull.cocci
Normal file
94
tools/coccinelle/itnull.cocci
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/// 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).
|
||||||
|
///
|
||||||
|
// Confidence: Moderate
|
||||||
|
// 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;
|
||||||
|
@@
|
||||||
|
|
||||||
|
I(x,...) { <...
|
||||||
|
(
|
||||||
|
- if (x == NULL && ...) S
|
||||||
|
|
|
||||||
|
- if (x != NULL || ...)
|
||||||
|
S
|
||||||
|
|
|
||||||
|
- (x == NULL) ||
|
||||||
|
E
|
||||||
|
|
|
||||||
|
- (x != NULL) &&
|
||||||
|
E
|
||||||
|
|
|
||||||
|
- (x == NULL && ...) ? E1 :
|
||||||
|
E2
|
||||||
|
|
|
||||||
|
- (x != NULL || ...) ?
|
||||||
|
E1
|
||||||
|
- : E2
|
||||||
|
|
|
||||||
|
- if (x == NULL && ...) S1 else
|
||||||
|
S2
|
||||||
|
|
|
||||||
|
- if (x != NULL || ...)
|
||||||
|
S1
|
||||||
|
- else S2
|
||||||
|
|
|
||||||
|
+ BAD(
|
||||||
|
x == NULL
|
||||||
|
+ )
|
||||||
|
|
|
||||||
|
+ BAD(
|
||||||
|
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)
|
98
tools/coccinelle/mini_lock.cocci
Normal file
98
tools/coccinelle/mini_lock.cocci
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/// Find missing unlocks. This semantic match considers the specific case
|
||||||
|
/// where the unlock is missing from an if branch, and there is a lock
|
||||||
|
/// before the if and an unlock after the if. False positives are due to
|
||||||
|
/// cases where the if branch represents a case where the function is
|
||||||
|
/// supposed to exit with the lock held, or where there is some preceding
|
||||||
|
/// function call that releases the lock.
|
||||||
|
///
|
||||||
|
// Confidence: Moderate
|
||||||
|
// 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
|
||||||
|
|
||||||
|
@prelocked@
|
||||||
|
position p1,p;
|
||||||
|
expression E1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
mutex_lock@p1
|
||||||
|
|
|
||||||
|
mutex_trylock@p1
|
||||||
|
|
|
||||||
|
spin_lock@p1
|
||||||
|
|
|
||||||
|
spin_trylock@p1
|
||||||
|
|
|
||||||
|
read_lock@p1
|
||||||
|
|
|
||||||
|
read_trylock@p1
|
||||||
|
|
|
||||||
|
write_lock@p1
|
||||||
|
|
|
||||||
|
write_trylock@p1
|
||||||
|
|
|
||||||
|
read_lock_irq@p1
|
||||||
|
|
|
||||||
|
write_lock_irq@p1
|
||||||
|
|
|
||||||
|
read_lock_irqsave@p1
|
||||||
|
|
|
||||||
|
write_lock_irqsave@p1
|
||||||
|
|
|
||||||
|
spin_lock_irq@p1
|
||||||
|
|
|
||||||
|
spin_lock_irqsave@p1
|
||||||
|
) (E1@p,...);
|
||||||
|
|
||||||
|
@looped@
|
||||||
|
position r;
|
||||||
|
@@
|
||||||
|
|
||||||
|
for(...;...;...) { <+... return@r ...; ...+> }
|
||||||
|
|
||||||
|
@err exists@
|
||||||
|
expression E1;
|
||||||
|
position prelocked.p;
|
||||||
|
position up != prelocked.p1;
|
||||||
|
position r!=looped.r;
|
||||||
|
identifier lock,unlock;
|
||||||
|
@@
|
||||||
|
|
||||||
|
*lock(E1@p,...);
|
||||||
|
... when != E1
|
||||||
|
when any
|
||||||
|
if (...) {
|
||||||
|
... when != E1
|
||||||
|
* return@r ...;
|
||||||
|
}
|
||||||
|
... when != E1
|
||||||
|
when any
|
||||||
|
*unlock@up(E1,...);
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << prelocked.p1;
|
||||||
|
lock << err.lock;
|
||||||
|
unlock << err.unlock;
|
||||||
|
p2 << err.r;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main(lock,p)
|
||||||
|
cocci.print_secs(unlock,p2)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << prelocked.p1;
|
||||||
|
lock << err.lock;
|
||||||
|
unlock << err.unlock;
|
||||||
|
p2 << err.r;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "preceding lock on line %s" % (p[0].line)
|
||||||
|
coccilib.report.print_report(p2[0],msg)
|
81
tools/coccinelle/noderef.cocci
Normal file
81
tools/coccinelle/noderef.cocci
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/// sizeof when applied to a pointer typed expression gives the size of
|
||||||
|
/// the pointer
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// 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 org
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
expression *x;
|
||||||
|
expression f;
|
||||||
|
expression i;
|
||||||
|
type T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
x = <+... sizeof(
|
||||||
|
- x
|
||||||
|
+ *x
|
||||||
|
) ...+>
|
||||||
|
|
|
||||||
|
f(...,(T)(x),...,sizeof(
|
||||||
|
- x
|
||||||
|
+ *x
|
||||||
|
),...)
|
||||||
|
|
|
||||||
|
f(...,sizeof(
|
||||||
|
- x
|
||||||
|
+ *x
|
||||||
|
),...,(T)(x),...)
|
||||||
|
|
|
||||||
|
f(...,(T)(x),...,i*sizeof(
|
||||||
|
- x
|
||||||
|
+ *x
|
||||||
|
),...)
|
||||||
|
|
|
||||||
|
f(...,i*sizeof(
|
||||||
|
- x
|
||||||
|
+ *x
|
||||||
|
),...,(T)(x),...)
|
||||||
|
)
|
||||||
|
|
||||||
|
@r depends on !patch@
|
||||||
|
expression *x;
|
||||||
|
expression f;
|
||||||
|
expression i;
|
||||||
|
position p;
|
||||||
|
type T;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
*x = <+... sizeof@p(x) ...+>
|
||||||
|
|
|
||||||
|
*f(...,(T)(x),...,sizeof@p(x),...)
|
||||||
|
|
|
||||||
|
*f(...,sizeof@p(x),...,(T)(x),...)
|
||||||
|
|
|
||||||
|
*f(...,(T)(x),...,i*sizeof@p(x),...)
|
||||||
|
|
|
||||||
|
*f(...,i*sizeof@p(x),...,(T)(x),...)
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("application of sizeof to pointer",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "ERROR: application of sizeof to pointer"
|
||||||
|
coccilib.report.print_report(p[0],msg)<Paste>
|
8
tools/coccinelle/replace-strncpy.cocci
Normal file
8
tools/coccinelle/replace-strncpy.cocci
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@@
|
||||||
|
type T;
|
||||||
|
T[] E;
|
||||||
|
expression buf, srclen;
|
||||||
|
@@
|
||||||
|
|
||||||
|
- strncpy(E, src, srclen)
|
||||||
|
+ strlcpy(E, src, sizeof(E))
|
66
tools/coccinelle/returnvar.cocci
Normal file
66
tools/coccinelle/returnvar.cocci
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
///
|
||||||
|
/// Remove unneeded variable used to store return value.
|
||||||
|
///
|
||||||
|
// Confidence: Moderate
|
||||||
|
// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Comments: Comments on code can be deleted if near code that is removed.
|
||||||
|
// "when strict" can be removed to get more hits, but adds false
|
||||||
|
// positives
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
type T;
|
||||||
|
constant C;
|
||||||
|
identifier ret;
|
||||||
|
@@
|
||||||
|
- T ret = C;
|
||||||
|
... when != ret
|
||||||
|
when strict
|
||||||
|
return
|
||||||
|
- ret
|
||||||
|
+ C
|
||||||
|
;
|
||||||
|
|
||||||
|
@depends on context@
|
||||||
|
type T;
|
||||||
|
constant C;
|
||||||
|
identifier ret;
|
||||||
|
@@
|
||||||
|
* T ret = C;
|
||||||
|
... when != ret
|
||||||
|
when strict
|
||||||
|
* return ret;
|
||||||
|
|
||||||
|
@r1 depends on report || org@
|
||||||
|
type T;
|
||||||
|
constant C;
|
||||||
|
identifier ret;
|
||||||
|
position p1, p2;
|
||||||
|
@@
|
||||||
|
T ret@p1 = C;
|
||||||
|
... when != ret
|
||||||
|
when strict
|
||||||
|
return ret@p2;
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p1 << r1.p1;
|
||||||
|
p2 << r1.p2;
|
||||||
|
C << r1.C;
|
||||||
|
ret << r1.ret;
|
||||||
|
@@
|
||||||
|
coccilib.report.print_report(p1[0], "Unneeded variable: \"" + ret + "\". Return \"" + C + "\" on line " + p2[0].line)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p1 << r1.p1;
|
||||||
|
p2 << r1.p2;
|
||||||
|
C << r1.C;
|
||||||
|
ret << r1.ret;
|
||||||
|
@@
|
||||||
|
cocci.print_main("unneeded \"" + ret + "\" variable", p1)
|
||||||
|
cocci.print_sec("return " + C + " here", p2)
|
83
tools/coccinelle/semicolon.cocci
Normal file
83
tools/coccinelle/semicolon.cocci
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
///
|
||||||
|
/// Remove unneeded semicolon.
|
||||||
|
///
|
||||||
|
// Confidence: Moderate
|
||||||
|
// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Comments: Some false positives on empty default cases in switch statements.
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
|
||||||
|
@r_default@
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
switch (...)
|
||||||
|
{
|
||||||
|
default: ...;@p
|
||||||
|
}
|
||||||
|
|
||||||
|
@r_case@
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
switch (...)
|
||||||
|
{
|
||||||
|
case ...:;@p
|
||||||
|
}
|
||||||
|
|
|
||||||
|
switch (...)
|
||||||
|
{
|
||||||
|
case ...:...
|
||||||
|
case ...:;@p
|
||||||
|
}
|
||||||
|
|
|
||||||
|
switch (...)
|
||||||
|
{
|
||||||
|
case ...:...
|
||||||
|
case ...:
|
||||||
|
case ...:;@p
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@r1@
|
||||||
|
statement S;
|
||||||
|
position p1;
|
||||||
|
position p != {r_default.p, r_case.p};
|
||||||
|
identifier label;
|
||||||
|
@@
|
||||||
|
(
|
||||||
|
label:;
|
||||||
|
|
|
||||||
|
S@p1;@p
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python@
|
||||||
|
p << r1.p;
|
||||||
|
p1 << r1.p1;
|
||||||
|
@@
|
||||||
|
if p[0].line != p1[0].line_end:
|
||||||
|
cocci.include_match(False)
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
position r1.p;
|
||||||
|
@@
|
||||||
|
-;@p
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r1.p;
|
||||||
|
@@
|
||||||
|
coccilib.report.print_report(p[0],"Unneeded semicolon")
|
||||||
|
|
||||||
|
@depends on context@
|
||||||
|
position r1.p;
|
||||||
|
@@
|
||||||
|
*;@p
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r1.p;
|
||||||
|
@@
|
||||||
|
cocci.print_main("Unneeded semicolon",p)
|
41
tools/coccinelle/strncpy_truncation.cocci
Normal file
41
tools/coccinelle/strncpy_truncation.cocci
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/// Use strlcpy rather than strncpy(dest,..,sz) + dest[sz-1] = '\0'
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
virtual context
|
||||||
|
virtual report
|
||||||
|
virtual org
|
||||||
|
|
||||||
|
@r@
|
||||||
|
expression dest, src, sz;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
strncpy@p(dest, src, sz);
|
||||||
|
dest[sz - 1] = '\0';
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("strncpy followed by truncation can be strlcpy",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "SUGGESTION: strncpy followed by truncation can be strlcpy"
|
||||||
|
coccilib.report.print_report(p[0],msg)
|
||||||
|
|
||||||
|
@ok depends on patch@
|
||||||
|
expression r.dest, r.src, r.sz;
|
||||||
|
position r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
-strncpy@p(
|
||||||
|
+strlcpy(
|
||||||
|
dest, src, sz);
|
||||||
|
-dest[sz - 1] = '\0';
|
75
tools/coccinelle/unsigned_lesser_than_zero.cocci
Normal file
75
tools/coccinelle/unsigned_lesser_than_zero.cocci
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/// Unsigned expressions cannot be lesser than zero. Presence of
|
||||||
|
/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug,
|
||||||
|
/// usually wrong type of variable.
|
||||||
|
///
|
||||||
|
/// To reduce number of false positives following tests have been added:
|
||||||
|
/// - parts of range checks are skipped, eg. "if (u < 0 || u > 15) ...",
|
||||||
|
/// developers prefer to keep such code,
|
||||||
|
/// - comparisons "<= 0" and "> 0" are performed only on results of
|
||||||
|
/// signed functions/macros,
|
||||||
|
/// - hardcoded list of signed functions/macros with always non-negative
|
||||||
|
/// result is used to avoid false positives difficult to detect by other ways
|
||||||
|
///
|
||||||
|
// Confidence: Average
|
||||||
|
// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Options: --all-includes
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@r_cmp@
|
||||||
|
position p;
|
||||||
|
typedef bool, u8, u16, u32, u64;
|
||||||
|
{unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long,
|
||||||
|
size_t, bool, u8, u16, u32, u64} v;
|
||||||
|
expression e;
|
||||||
|
@@
|
||||||
|
|
||||||
|
\( v = e \| &v \)
|
||||||
|
...
|
||||||
|
(\( v@p < 0 \| v@p <= 0 \| v@p >= 0 \| v@p > 0 \))
|
||||||
|
|
||||||
|
@r@
|
||||||
|
position r_cmp.p;
|
||||||
|
typedef s8, s16, s32, s64;
|
||||||
|
{char, short, int, long, long long, ssize_t, s8, s16, s32, s64} vs;
|
||||||
|
expression c, e, v;
|
||||||
|
identifier f !~ "^(ata_id_queue_depth|btrfs_copy_from_user|dma_map_sg|dma_map_sg_attrs|fls|fls64|gameport_time|get_write_extents|nla_len|ntoh24|of_flat_dt_match|of_get_child_count|uart_circ_chars_pending|[A-Z0-9_]+)$";
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
v = f(...)@vs;
|
||||||
|
... when != v = e;
|
||||||
|
* (\( v@p <=@e 0 \| v@p >@e 0 \))
|
||||||
|
... when any
|
||||||
|
|
|
||||||
|
(
|
||||||
|
(\( v@p < 0 \| v@p <= 0 \)) || ... || (\( v >= c \| v > c \))
|
||||||
|
|
|
||||||
|
(\( v >= c \| v > c \)) || ... || (\( v@p < 0 \| v@p <= 0 \))
|
||||||
|
|
|
||||||
|
(\( v@p >= 0 \| v@p > 0 \)) && ... && (\( v < c \| v <= c \))
|
||||||
|
|
|
||||||
|
((\( v < c \| v <= c \) && ... && \( v@p >= 0 \| v@p > 0 \)))
|
||||||
|
|
|
||||||
|
* (\( v@p <@e 0 \| v@p >=@e 0 \))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r_cmp.p;
|
||||||
|
e << r.e;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
|
||||||
|
coccilib.org.print_todo(p[0], msg)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r_cmp.p;
|
||||||
|
e << r.e;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
|
||||||
|
coccilib.report.print_report(p[0], msg)
|
52
tools/coccinelle/xcalloc-simple.cocci
Normal file
52
tools/coccinelle/xcalloc-simple.cocci
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
///
|
||||||
|
/// Use zeroing allocator rather than allocator followed by memset with 0
|
||||||
|
///
|
||||||
|
/// This considers some simple cases that are common and easy to validate
|
||||||
|
/// Note in particular that there are no ...s in the rule, so all of the
|
||||||
|
/// matched code has to be contiguous
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2.
|
||||||
|
// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||||
|
// Copyright: (C) 2017 Himanshu Jha GPLv2.
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
//
|
||||||
|
// Keywords: XMALLOC, XCALLOC
|
||||||
|
// Version min: < 2.6.12 kmalloc
|
||||||
|
// Version min: 2.6.14 kzalloc
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual context
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For context mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on context@
|
||||||
|
type T, T2;
|
||||||
|
expression x;
|
||||||
|
expression E1;
|
||||||
|
expression t;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* x = (T)XMALLOC(t, E1);
|
||||||
|
* memset((T2)x,0,E1);
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
type T, T2;
|
||||||
|
expression x;
|
||||||
|
expression E1;
|
||||||
|
expression t;
|
||||||
|
@@
|
||||||
|
|
||||||
|
- x = (T)XMALLOC(t, E1);
|
||||||
|
+ x = (T)XCALLOC(t, E1);
|
||||||
|
- memset((T2)x,0,E1);
|
||||||
|
|
122
tools/coccinelle/xfree.cocci
Normal file
122
tools/coccinelle/xfree.cocci
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/// Find a use after free.
|
||||||
|
//# Values of variables may imply that some
|
||||||
|
//# execution paths are not possible, resulting in false positives.
|
||||||
|
//# Another source of false positives are macros such as
|
||||||
|
//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
|
||||||
|
///
|
||||||
|
// Confidence: Moderate
|
||||||
|
// 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.
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
|
||||||
|
@free@
|
||||||
|
expression E, t;
|
||||||
|
position p1;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* XFREE@p1(t, E)
|
||||||
|
|
||||||
|
@print expression@
|
||||||
|
constant char [] c;
|
||||||
|
expression free.E,E2;
|
||||||
|
type T;
|
||||||
|
position p;
|
||||||
|
identifier f;
|
||||||
|
@@
|
||||||
|
|
||||||
|
(
|
||||||
|
f(...,c,...,(T)E@p,...)
|
||||||
|
|
|
||||||
|
E@p == E2
|
||||||
|
|
|
||||||
|
E@p != E2
|
||||||
|
|
|
||||||
|
E2 == E@p
|
||||||
|
|
|
||||||
|
E2 != E@p
|
||||||
|
|
|
||||||
|
!E@p
|
||||||
|
|
|
||||||
|
E@p || ...
|
||||||
|
)
|
||||||
|
|
||||||
|
@sz@
|
||||||
|
expression free.E;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
sizeof(<+...E@p...+>)
|
||||||
|
|
||||||
|
@loop exists@
|
||||||
|
expression E, t;
|
||||||
|
identifier l;
|
||||||
|
position ok;
|
||||||
|
@@
|
||||||
|
|
||||||
|
while (1) { ...
|
||||||
|
* XFREE@ok(t, E)
|
||||||
|
... when != break;
|
||||||
|
when != goto l;
|
||||||
|
when forall
|
||||||
|
}
|
||||||
|
|
||||||
|
@r exists@
|
||||||
|
expression free.E, subE<=free.E, E2;
|
||||||
|
expression E1;
|
||||||
|
iterator iter;
|
||||||
|
statement S;
|
||||||
|
position free.p1!=loop.ok,p2!={print.p,sz.p};
|
||||||
|
@@
|
||||||
|
|
||||||
|
* XFREE@p1(t, E)
|
||||||
|
...
|
||||||
|
(
|
||||||
|
iter(...,subE,...) S // no use
|
||||||
|
|
|
||||||
|
list_remove_head(E1,subE,...)
|
||||||
|
|
|
||||||
|
subE = E2
|
||||||
|
|
|
||||||
|
subE++
|
||||||
|
|
|
||||||
|
++subE
|
||||||
|
|
|
||||||
|
--subE
|
||||||
|
|
|
||||||
|
subE--
|
||||||
|
|
|
||||||
|
&subE
|
||||||
|
|
|
||||||
|
BUG(...)
|
||||||
|
|
|
||||||
|
BUG_ON(...)
|
||||||
|
|
|
||||||
|
return_VALUE(...)
|
||||||
|
|
|
||||||
|
return_ACPI_STATUS(...)
|
||||||
|
|
|
||||||
|
E@p2 // bad use
|
||||||
|
)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p1 << free.p1;
|
||||||
|
p2 << r.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("kfree",p1)
|
||||||
|
cocci.print_secs("ref",p2)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p1 << free.p1;
|
||||||
|
p2 << r.p2;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
|
||||||
|
coccilib.report.print_report(p2[0],msg)
|
33
tools/coccinelle/xfreeaddr.cocci
Normal file
33
tools/coccinelle/xfreeaddr.cocci
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/// Free of a structure field
|
||||||
|
///
|
||||||
|
// Confidence: High
|
||||||
|
// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2.
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
// URL: http://coccinelle.lip6.fr/
|
||||||
|
// Comments:
|
||||||
|
// Options: --no-includes --include-headers
|
||||||
|
|
||||||
|
virtual org
|
||||||
|
virtual report
|
||||||
|
virtual context
|
||||||
|
|
||||||
|
@r depends on context || report || org @
|
||||||
|
expression e, t;
|
||||||
|
identifier f;
|
||||||
|
position p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
* XFREE@p(t, &e->f)
|
||||||
|
|
||||||
|
@script:python depends on org@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
cocci.print_main("XFREE",p)
|
||||||
|
|
||||||
|
@script:python depends on report@
|
||||||
|
p << r.p;
|
||||||
|
@@
|
||||||
|
|
||||||
|
msg = "ERROR: invalid free of structure field"
|
||||||
|
coccilib.report.print_report(p[0],msg)
|
37
tools/coccinelle/xmalloc_returnval.cocci
Normal file
37
tools/coccinelle/xmalloc_returnval.cocci
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/// XMALLOC, XCALLOC etc either return non-null, or abort the program.
|
||||||
|
/// Never nullcheck these.
|
||||||
|
//
|
||||||
|
// Copyright: (C) 2019 Quentin Young. GPLv2.
|
||||||
|
|
||||||
|
virtual patch
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// For patch mode
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
identifier alloc;
|
||||||
|
@@
|
||||||
|
|
||||||
|
alloc = XMALLOC(...);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
- if (alloc == NULL)
|
||||||
|
- {
|
||||||
|
- ...
|
||||||
|
- }
|
||||||
|
|
||||||
|
@depends on patch@
|
||||||
|
identifier alloc;
|
||||||
|
@@
|
||||||
|
|
||||||
|
alloc = XCALLOC(...);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
- if (alloc == NULL)
|
||||||
|
- {
|
||||||
|
- ...
|
||||||
|
- }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user