a Scala Compiler Plugin for Verification
Nada Amin
a Scala Compiler Plugin for Verification Nada Amin Features - - PowerPoint PPT Presentation
a Scala Compiler Plugin for Verification Nada Amin Features transform Scala def AST into a CFG front-end to lab verifier front-end to Eldarica support for design by contract partial understanding verified classes
Nada Amin
@verify def counter(length: Int) { assume(length > 0) var i: Int = 0 var j: Int = 1 assert(j <= length) while(j < length) { i = j - 1 assert(j < length) while(i >= 0) { i = i - 1 } j = j + 1 } assert(j == length) }
@verify def even(n: Int): Int = { precondition(n >= 0) var r = 0 if (n == 0) r = 1 else if (n == 1) r = 0 else r = odd(n-1) postcondition(r == 0 || r == 1) r } @verify def odd(n: Int): Int = { precondition(n >= 0) var r = 0 if (n == 0) r = 0 else if (n == 1) r = 1 else r = even(n-1) postcondition(r == 0 || r == 1) r }
@verify def even(n: Int): Int = { precondition(n >= 0) var r = 0 if (n == 0) r = 1 else if (n == 1) r = 0 else r = odd(n-1) postcondition(r == 0 || r == 1) r }
val random = new scala.util.Random() def havoc = random.nextInt - random.nextInt @verify def partition(b: Int) = { precondition(b >= 0) var P1:Int = 0 var P2:Int = 0 var a: Int = b var h: Int = 0 while(a > 0) { h = havoc if(h >= 0) P1 = P1 + 1 else P2 = P2 + 1 a = a - 1 } assert(P1 + P2 == b) val result = P1 postcondition(result <= b) result } }
@verify def test(queue: Queue) { var l = 0 var oldi = 0 var newi = 0 var q = queue do { l = lock(l)
if (q.next != None) { q = q.next.get q.data = newi l = unlock(l) newi += 1 } } while (newi != oldi) l = unlock(l) } ((l == 0 && newi != oldi) || (l == 1 && newi == oldi))
@verify def lock(l: Int) = { precondition(l == 0) val r = 1 postcondition(r == 1) r } @verify def unlock(l: Int) = { precondition(l == 1) val r = 0 postcondition(r == 0) r } class Queue(var data: Int, var next: Option[Queue])
@verify class BankAccount { var balance = 0 @verify def withdraw(amount: Int) { precondition(amount >= 0 && balance >= amount) val old_balance = old(balance) balance -= amount postcondition(balance == old_balance - amount && balance >= 0) } @verify def deposit(amount: Int) { precondition(amount >= 0 && balance >= 0) val old_balance = old(balance) balance += amount postcondition(balance == old_balance + amount && balance >= 0) } }
@verify class DoubleBankAccount { val savings = new BankAccount val checking = new BankAccount @verify def transfer(amount: Int) { precondition(amount >= 0 && savings.balance >= amount && checking.balance >= 0) val old_savings_balance = old(savings.balance) val old_checking_balance = old(checking.balance) savings.withdraw(amount) checking.deposit(amount) postcondition(savings.balance + checking.balance ==
savings.balance >= 0 && checking.balance >= 0) } }
invariants
counterexample
Model for counterexample: == step 1 == length ← 2 == step 2 == i ← 0 == step 3 == j ← 1 == step 4 == i ← -1 == step 5 == j ← 3 == final values == i ← -1 j ← 3 length ← 2 The program has a bug in asserting: (j == length) @verify def test(length: Int) { assume(length > 0) var i: Int = 0 var j: Int = 1 while(j < length) { i = j - 1 while(i >= 0) { i = i - 1 } j = j + 2 // should be 1 } assert(j == length) }
def alwaysTrue() = true @verify def test() = { var x = 0 if (alwaysTrue()) { x += 1 } if (alwaysTrue()) { x -= 1 } postcondition(x == 0) x } Model for counterexample: == step 1 == x ← 0 == step 2 == x ← -1 == final values == x ← -1 The program has a bug in asserting: (x == 0)
warning: ignoring any aliasing involving other successfully verified withdraw with 1 warning(s)
@verify class BankAccount { var balance = 0 @verify def withdraw(amount: Int, other: BankAccount) { precondition(amount >= 0 && balance >= amount) val old_balance = old(balance) balance -= amount
postcondition(balance == old_balance - amount && balance >= 0) } }