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-2012 Nicolas Palix. GPLv2. 10// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. 11// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. 12// URL: http://coccinelle.lip6.fr/ 13 14virtual context 15virtual org 16virtual report 17 18@prelocked depends on !(file in "ext")@ 19position p1,p; 20expression E1; 21@@ 22 23( 24irq_lock@p1 25| 26k_mutex_lock@p1 27| 28k_sem_take@p1 29| 30k_spin_lock@p1 31) (E1@p,...); 32 33@looped depends on !(file in "ext")@ 34position r; 35@@ 36 37for(...;...;...) { <+... return@r ...; ...+> } 38 39@balanced exists@ 40position p1 != prelocked.p1; 41position prelocked.p; 42position pif; 43identifier lock,unlock; 44expression x <= prelocked.E1; 45expression E,prelocked.E1; 46expression E2; 47@@ 48 49if (E) { 50 ... when != E1 51 lock(E1@p,...) 52 ... when any 53} 54... when != E1 55 when != \(x = E2\|&x\) 56if@pif (E) { 57 ... when != E1 58 unlock@p1(E1,...) 59 ... when any 60} 61 62@err depends on !(file in "ext") exists@ 63expression E1; 64position prelocked.p,balanced.pif; 65position up != prelocked.p1; 66position r!=looped.r; 67identifier lock,unlock; 68statement S1,S2; 69@@ 70 71*lock(E1@p,...); 72... when != E1 73 when any 74 when != if@pif (...) S1 75if (...) { 76 ... when != E1 77 when != if@pif (...) S2 78* return@r ...; 79} 80... when != E1 81 when any 82*unlock@up(E1,...); 83 84@script:python depends on org@ 85p << prelocked.p1; 86lock << err.lock; 87unlock << err.unlock; 88p2 << err.r; 89@@ 90 91cocci.print_main(lock,p) 92cocci.print_secs(unlock,p2) 93 94@script:python depends on report@ 95p << prelocked.p1; 96lock << err.lock; 97unlock << err.unlock; 98p2 << err.r; 99@@ 100 101msg = "preceding lock on line %s" % (p[0].line) 102coccilib.report.print_report(p2[0],msg) 103