T.Ball R.Majumdar T.Millstein S.K.Rajamani ...anna.fi.muni.cz/data/pres/2017-autumn/mrazek.pdf ·...
Transcript of T.Ball R.Majumdar T.Millstein S.K.Rajamani ...anna.fi.muni.cz/data/pres/2017-autumn/mrazek.pdf ·...
Automatic Predicate Abstraction of C Programs
T. Ball R. Majumdar T. Millstein S. K. Rajamanipresented by Jan Mrázek
Masaryk UniversityBrno, Czech Republic
16th October 2017
1 / 18
Motivation
model checking has been successful in validatingmodelsprotocolshardware
it struggles witharithmetics (finite-state systems)heap manipulation (inifinite-state systems)
Solution: use abstraction
2 / 18
Motivation
model checking has been successful in validatingmodelsprotocolshardware
it struggles witharithmetics (finite-state systems)heap manipulation (inifinite-state systems)
Solution: use abstraction
2 / 18
Predicate Abstraction in a Nutshell
idea:do not keep full stateskeep only truth values of predicates over data
abstract function: α(s) = (p1(s), p2(s), ..., pn(s))
challenge: correctly and efficiently compute transitions
3 / 18
Predicate Abstraction in a Nutshell
idea:do not keep full stateskeep only truth values of predicates over data
abstract function: α(s) = (p1(s), p2(s), ..., pn(s))
challenge: correctly and efficiently compute transitions
3 / 18
Predicate Abstraction in C2BP
Input:
C program Pno restrictions except concurrency and interprocedural jumps
set E of predicatespure C boolean expressionsno function callse.g. {x < y, x > 0}
Output:
boolean program BP(P,E )C program with several extensionsonly boolean variablesnumber of variables = |E |
4 / 18
Example – List Partitiontypedef struct cell { int val; struct cell* next;} *list;
list partition(list *l, int v) {list curr, prev, newl, nextCurr;curr = *l; prev = NULL; newl = NULL;while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}5 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {list curr, prev, newl, nextCurr;curr = *l; prev = NULL; newl = NULL;while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
} 6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {list curr, prev, newl, nextCurr;curr = *l; prev = NULL; newl = NULL;while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
} 6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};curr = *l; prev = NULL; newl = NULL;while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};curr = *l; prev = NULL; newl = NULL;while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (curr != NULL) {
nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});nextCurr = curr->next;if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});skip();if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});skip();if (curr->val > v) {
if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});skip();if (choose(2)) {
assume({cur->val>v});if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});skip();if (choose(2)) {
assume({cur->val>v});if (prev != NULL) prev->next = nextCurr;if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Boolean Program Example – List PartitionE = { curr == NULL, prev == NULL, curr->val > v,prev->val > v }
list partition(list *l, int v) {bool {curr==NULL}, {prev==NULL};bool {curr->val>v}, {prev->val>v};{curr==NULL} = unknown();{prev==NULL} = true;{curr->val>v} = unknown();{prev->val>v} = unknown();while (choose(2)) {
assume(!{curr==NULL});skip();if (choose(2)) {
assume({cur->val>v});if (choose(2)){
assume(!{(prev==NULL});prev->next = nextCurr;
if (curr == *l) *l = nextCurr;curr->next = newl; newl = curr;
} elseprev = curr;
curr = nextCurr;}return newl;
}
6 / 18
Properties of Boolean Programs
BP(P,E ):
has the same control-flow as Pcontains only |E | boolean variablesis an over-approximation of P
7 / 18
Preprocessing
control flow is expressed usingif-then-elsegoto
all expressions are side-effect freeno short-circuit evaluation
if ( a || b ) { /*body*/ }if ( a ) { /*body*/ } else if ( b ) { /*body*/ }
no multiple dereferences of a pointer**p;int *x = *p; *x;
call only at the top-most level of an expressionz = x + f( y );t = f( y ); z = x + t;
8 / 18
Updating Boolean Variables I
We need to define rules for updating variables’ values.
For statement s and a predicate ϕ:
denote WP(s, ϕ) as the weakest preconditionweakest predicate before s entailing truth of ϕ after sexample:
WP(x = x + 1, x < 5) = (x + 1) < 5 = (x < 4)
let b be a corresponding boolean variable to ϕif ϕ ∈ E and b is true before s, b is true after s
“if x < 4 is true before x = x + 1, then x < 5 is trueafterwards”
9 / 18
Updating Boolean Variables I
We need to define rules for updating variables’ values.
For statement s and a predicate ϕ:
denote WP(s, ϕ) as the weakest preconditionweakest predicate before s entailing truth of ϕ after sexample:
WP(x = x + 1, x < 5) = (x + 1) < 5 = (x < 4)
let b be a corresponding boolean variable to ϕif ϕ ∈ E and b is true before s, b is true after s
“if x < 4 is true before x = x + 1, then x < 5 is trueafterwards”
9 / 18
Updating Boolean Variables I
We need to define rules for updating variables’ values.
For statement s and a predicate ϕ:
denote WP(s, ϕ) as the weakest preconditionweakest predicate before s entailing truth of ϕ after sexample:
WP(x = x + 1, x < 5) = (x + 1) < 5 = (x < 4)
let b be a corresponding boolean variable to ϕif ϕ ∈ E and b is true before s, b is true after s
“if x < 4 is true before x = x + 1, then x < 5 is trueafterwards”
9 / 18
Updating Boolean Variables I
We need to define rules for updating variables’ values.
For statement s and a predicate ϕ:
denote WP(s, ϕ) as the weakest preconditionweakest predicate before s entailing truth of ϕ after sexample:
WP(x = x + 1, x < 5) = (x + 1) < 5 = (x < 4)
let b be a corresponding boolean variable to ϕif ϕ ∈ E and b is true before s, b is true after s
“if x < 4 is true before x = x + 1, then x < 5 is trueafterwards”
9 / 18
Updating Boolean Variables II
if ϕ /∈ E we strenghten ϕonly over expressions in E
example:
E = {x < 5, x = 2}WP(x = x + 1, x < 5) = (x < 4)
x = 2 =⇒ x < 4
“if x = 2 before x = x + 1, then x < 5 is true afterwards”
10 / 18
Updating Boolean Variables II
if ϕ /∈ E we strenghten ϕonly over expressions in E
example:
E = {x < 5, x = 2}WP(x = x + 1, x < 5) = (x < 4)
x = 2 =⇒ x < 4
“if x = 2 before x = x + 1, then x < 5 is true afterwards”
10 / 18
Strengtening of a Predicate
denote V as a set of boolean variables {b1, b2, · · · , bn}cube over V is a conjunction c1 ∧ c2 ∧ · · · ∧ ck whereci ∈ {bi ,¬bi}denote E(bi ) as a corresponding predicate ϕi to biextend E to cubes
Fv (ϕ) – the largest disjuntion of cubes over V such that:E(c) =⇒ ϕ
use theorem prover for validating strenghtenings
define weakening as Gv (ϕ) = ¬FV (¬ϕ)
11 / 18
Strengtening of a Predicate
denote V as a set of boolean variables {b1, b2, · · · , bn}cube over V is a conjunction c1 ∧ c2 ∧ · · · ∧ ck whereci ∈ {bi ,¬bi}denote E(bi ) as a corresponding predicate ϕi to biextend E to cubes
Fv (ϕ) – the largest disjuntion of cubes over V such that:E(c) =⇒ ϕ
use theorem prover for validating strenghtenings
define weakening as Gv (ϕ) = ¬FV (¬ϕ)
11 / 18
Strengtening of a Predicate
denote V as a set of boolean variables {b1, b2, · · · , bn}cube over V is a conjunction c1 ∧ c2 ∧ · · · ∧ ck whereci ∈ {bi ,¬bi}denote E(bi ) as a corresponding predicate ϕi to biextend E to cubes
Fv (ϕ) – the largest disjuntion of cubes over V such that:E(c) =⇒ ϕ
use theorem prover for validating strenghtenings
define weakening as Gv (ϕ) = ¬FV (¬ϕ)
11 / 18
Strengtening of a Predicate
denote V as a set of boolean variables {b1, b2, · · · , bn}cube over V is a conjunction c1 ∧ c2 ∧ · · · ∧ ck whereci ∈ {bi ,¬bi}denote E(bi ) as a corresponding predicate ϕi to biextend E to cubes
Fv (ϕ) – the largest disjuntion of cubes over V such that:E(c) =⇒ ϕ
use theorem prover for validating strenghtenings
define weakening as Gv (ϕ) = ¬FV (¬ϕ)
11 / 18
Handling Aliases
when pointers are present, WP(x = e, ϕ) 6= ϕ[e/x ]example WP(x = 3, *p > 5) when &x = p
two cases:x and p are aliasesx and p are distinct
WP(x = 3, *p > 5) = (&x = p ∧ 3 > 5)∨ (&x 6= p ∧ ∗p > 5)for k possible aliases, there will be 2k disjunctsuse a pointer may analysis to prune the disjuncts
12 / 18
Handling Aliases
when pointers are present, WP(x = e, ϕ) 6= ϕ[e/x ]example WP(x = 3, *p > 5) when &x = p
two cases:x and p are aliasesx and p are distinct
WP(x = 3, *p > 5) = (&x = p ∧ 3 > 5)∨ (&x 6= p ∧ ∗p > 5)for k possible aliases, there will be 2k disjunctsuse a pointer may analysis to prune the disjuncts
12 / 18
Handling Assignments
assignment yields parallel assignment to all boolean variablesbi can be after assignment
true if Fv (WP(x = e, ϕ)) holds before assignmentfalse if Fv (WP(x = e,¬ϕ)) holds before assignment
if neither holds, assign non-deterministic value
13 / 18
Handling Gotos
no dependency on Vcopy them to BP
14 / 18
Handling Conditionals
if (ϕ) { ... } else { ... }:ϕ holds in then branch → GV (ϕ) holds¬ϕ holds in else branch → GV (¬ϕ) holds
if ( choose(2) ) {assume( G_V( phi ) )...
}else {
assume( G_V( !phi ) )...
}
15 / 18
Handling Conditionals
if (ϕ) { ... } else { ... }:ϕ holds in then branch → GV (ϕ) holds¬ϕ holds in else branch → GV (¬ϕ) holds
if ( choose(2) ) {assume( G_V( phi ) )...
}else {
assume( G_V( !phi ) )...
}
15 / 18
Handling Function Calls
local predicates vs. global predicateseach function can be transformed independently
arguments – values of local predicates referring to formalparametersreturn value – tuple of updated global and local predicates
when calling functioncompute actual value of formal arguments (predicates)call and store return value to a new tuple of variableupdate local and global predicates (take aliasing into account)
16 / 18
The Enforce Construct
predicates might be correlatede.g. x = 1 and x = 2
enforce(Φ)
put assume(Φ) between every two statements in a procedure
Φ = FV (false)
17 / 18
Optimizations
theorem prover running time is dominatingup to exponentially many calls
prune cubesconsider cubes in increasing lengthdetect cubes implying ¬ϕ
use heuristics to limit predicatescone of influence to reduce number of variables in Fconstruct F syntacticallycache computations
sacrifice precision and limit length of cubes
18 / 18
Optimizations
theorem prover running time is dominatingup to exponentially many calls
prune cubesconsider cubes in increasing lengthdetect cubes implying ¬ϕ
use heuristics to limit predicatescone of influence to reduce number of variables in Fconstruct F syntacticallycache computations
sacrifice precision and limit length of cubes
18 / 18
Optimizations
theorem prover running time is dominatingup to exponentially many calls
prune cubesconsider cubes in increasing lengthdetect cubes implying ¬ϕ
use heuristics to limit predicatescone of influence to reduce number of variables in Fconstruct F syntacticallycache computations
sacrifice precision and limit length of cubes
18 / 18