0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /// Find missing unlocks. This semantic match considers the specific case
0003 /// where the unlock is missing from an if branch, and there is a lock
0004 /// before the if and an unlock after the if. False positives are due to
0005 /// cases where the if branch represents a case where the function is
0006 /// supposed to exit with the lock held, or where there is some preceding
0007 /// function call that releases the lock.
0008 ///
0009 // Confidence: Moderate
0010 // Copyright: (C) 2010-2012 Nicolas Palix.
0011 // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
0012 // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
0013 // URL: https://coccinelle.gitlabpages.inria.fr/website
0014 // Comments:
0015 // Options: --no-includes --include-headers
0016
0017 virtual context
0018 virtual org
0019 virtual report
0020
0021 @prelocked@
0022 position p1,p;
0023 expression E1;
0024 @@
0025
0026 (
0027 mutex_lock@p1
0028 |
0029 mutex_trylock@p1
0030 |
0031 spin_lock@p1
0032 |
0033 spin_trylock@p1
0034 |
0035 read_lock@p1
0036 |
0037 read_trylock@p1
0038 |
0039 write_lock@p1
0040 |
0041 write_trylock@p1
0042 |
0043 read_lock_irq@p1
0044 |
0045 write_lock_irq@p1
0046 |
0047 read_lock_irqsave@p1
0048 |
0049 write_lock_irqsave@p1
0050 |
0051 spin_lock_irq@p1
0052 |
0053 spin_lock_irqsave@p1
0054 ) (E1@p,...);
0055
0056 @looped@
0057 position r;
0058 @@
0059
0060 for(...;...;...) { <+... return@r ...; ...+> }
0061
0062 @err exists@
0063 expression E1;
0064 position prelocked.p;
0065 position up != prelocked.p1;
0066 position r!=looped.r;
0067 identifier lock,unlock;
0068 @@
0069
0070 *lock(E1@p,...);
0071 ... when != E1
0072 when any
0073 if (...) {
0074 ... when != E1
0075 * return@r ...;
0076 }
0077 ... when != E1
0078 when any
0079 *unlock@up(E1,...);
0080
0081 @script:python depends on org@
0082 p << prelocked.p1;
0083 lock << err.lock;
0084 unlock << err.unlock;
0085 p2 << err.r;
0086 @@
0087
0088 cocci.print_main(lock,p)
0089 cocci.print_secs(unlock,p2)
0090
0091 @script:python depends on report@
0092 p << prelocked.p1;
0093 lock << err.lock;
0094 unlock << err.unlock;
0095 p2 << err.r;
0096 @@
0097
0098 msg = "preceding lock on line %s" % (p[0].line)
0099 coccilib.report.print_report(p2[0],msg)