1*4882a593Smuzhiyun// SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun/// Find missing unlocks. This semantic match considers the specific case 3*4882a593Smuzhiyun/// where the unlock is missing from an if branch, and there is a lock 4*4882a593Smuzhiyun/// before the if and an unlock after the if. False positives are due to 5*4882a593Smuzhiyun/// cases where the if branch represents a case where the function is 6*4882a593Smuzhiyun/// supposed to exit with the lock held, or where there is some preceding 7*4882a593Smuzhiyun/// function call that releases the lock. 8*4882a593Smuzhiyun/// 9*4882a593Smuzhiyun// Confidence: Moderate 10*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Nicolas Palix. 11*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. 12*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. 13*4882a593Smuzhiyun// URL: http://coccinelle.lip6.fr/ 14*4882a593Smuzhiyun// Comments: 15*4882a593Smuzhiyun// Options: --no-includes --include-headers 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunvirtual context 18*4882a593Smuzhiyunvirtual org 19*4882a593Smuzhiyunvirtual report 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun@prelocked@ 22*4882a593Smuzhiyunposition p1,p; 23*4882a593Smuzhiyunexpression E1; 24*4882a593Smuzhiyun@@ 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun( 27*4882a593Smuzhiyunmutex_lock@p1 28*4882a593Smuzhiyun| 29*4882a593Smuzhiyunmutex_trylock@p1 30*4882a593Smuzhiyun| 31*4882a593Smuzhiyunspin_lock@p1 32*4882a593Smuzhiyun| 33*4882a593Smuzhiyunspin_trylock@p1 34*4882a593Smuzhiyun| 35*4882a593Smuzhiyunread_lock@p1 36*4882a593Smuzhiyun| 37*4882a593Smuzhiyunread_trylock@p1 38*4882a593Smuzhiyun| 39*4882a593Smuzhiyunwrite_lock@p1 40*4882a593Smuzhiyun| 41*4882a593Smuzhiyunwrite_trylock@p1 42*4882a593Smuzhiyun| 43*4882a593Smuzhiyunread_lock_irq@p1 44*4882a593Smuzhiyun| 45*4882a593Smuzhiyunwrite_lock_irq@p1 46*4882a593Smuzhiyun| 47*4882a593Smuzhiyunread_lock_irqsave@p1 48*4882a593Smuzhiyun| 49*4882a593Smuzhiyunwrite_lock_irqsave@p1 50*4882a593Smuzhiyun| 51*4882a593Smuzhiyunspin_lock_irq@p1 52*4882a593Smuzhiyun| 53*4882a593Smuzhiyunspin_lock_irqsave@p1 54*4882a593Smuzhiyun) (E1@p,...); 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun@looped@ 57*4882a593Smuzhiyunposition r; 58*4882a593Smuzhiyun@@ 59*4882a593Smuzhiyun 60*4882a593Smuzhiyunfor(...;...;...) { <+... return@r ...; ...+> } 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun@err exists@ 63*4882a593Smuzhiyunexpression E1; 64*4882a593Smuzhiyunposition prelocked.p; 65*4882a593Smuzhiyunposition up != prelocked.p1; 66*4882a593Smuzhiyunposition r!=looped.r; 67*4882a593Smuzhiyunidentifier lock,unlock; 68*4882a593Smuzhiyun@@ 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun*lock(E1@p,...); 71*4882a593Smuzhiyun... when != E1 72*4882a593Smuzhiyun when any 73*4882a593Smuzhiyunif (...) { 74*4882a593Smuzhiyun ... when != E1 75*4882a593Smuzhiyun* return@r ...; 76*4882a593Smuzhiyun} 77*4882a593Smuzhiyun... when != E1 78*4882a593Smuzhiyun when any 79*4882a593Smuzhiyun*unlock@up(E1,...); 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun@script:python depends on org@ 82*4882a593Smuzhiyunp << prelocked.p1; 83*4882a593Smuzhiyunlock << err.lock; 84*4882a593Smuzhiyununlock << err.unlock; 85*4882a593Smuzhiyunp2 << err.r; 86*4882a593Smuzhiyun@@ 87*4882a593Smuzhiyun 88*4882a593Smuzhiyuncocci.print_main(lock,p) 89*4882a593Smuzhiyuncocci.print_secs(unlock,p2) 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun@script:python depends on report@ 92*4882a593Smuzhiyunp << prelocked.p1; 93*4882a593Smuzhiyunlock << err.lock; 94*4882a593Smuzhiyununlock << err.unlock; 95*4882a593Smuzhiyunp2 << err.r; 96*4882a593Smuzhiyun@@ 97*4882a593Smuzhiyun 98*4882a593Smuzhiyunmsg = "preceding lock on line %s" % (p[0].line) 99*4882a593Smuzhiyuncoccilib.report.print_report(p2[0],msg) 100