1/// Find missing unlocks.  This semantic match considers the specific case
2/// where the unlock is missing from an if branch, and there is a lock
3/// before the if and an unlock after the if.  False positives are due to
4/// cases where the if branch represents a case where the function is
5/// supposed to exit with the lock held, or where there is some preceding
6/// function call that releases the lock.
7///
8// Confidence: Moderate
9// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
10// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
11// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
12// URL: http://coccinelle.lip6.fr/
13// Comments:
14// Options: -no_includes -include_headers
15
16virtual org
17virtual report
18
19@prelocked@
20position p1,p;
21expression E1;
22@@
23
24(
25mutex_lock@p1
26|
27mutex_trylock@p1
28|
29spin_lock@p1
30|
31spin_trylock@p1
32|
33read_lock@p1
34|
35read_trylock@p1
36|
37write_lock@p1
38|
39write_trylock@p1
40|
41read_lock_irq@p1
42|
43write_lock_irq@p1
44|
45read_lock_irqsave@p1
46|
47write_lock_irqsave@p1
48|
49spin_lock_irq@p1
50|
51spin_lock_irqsave@p1
52) (E1@p,...);
53
54@looped@
55position r;
56@@
57
58for(...;...;...) { <+... return@r ...; ...+> }
59
60@err@
61expression E1;
62position prelocked.p;
63position up != prelocked.p1;
64position r!=looped.r;
65identifier lock,unlock;
66@@
67
68lock(E1@p,...);
69<+... when != E1
70if (...) {
71  ... when != E1
72  return@r ...;
73}
74...+>
75unlock@up(E1,...);
76
77@script:python depends on org@
78p << prelocked.p1;
79lock << err.lock;
80unlock << err.unlock;
81p2 << err.r;
82@@
83
84cocci.print_main(lock,p)
85cocci.print_secs(unlock,p2)
86
87@script:python depends on report@
88p << prelocked.p1;
89lock << err.lock;
90unlock << err.unlock;
91p2 << err.r;
92@@
93
94msg = "preceding lock on line %s" % (p[0].line)
95coccilib.report.print_report(p2[0],msg)
96