mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 20:27:14 +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