250 likes | 264 Views
Tool-supported Program Abstraction for Finite-state Verification. Matthew Dwyer 1 , John Hatcliff 1 , Corina Pasareanu 1 , Robby 1 , Roby Joehanes 1 , Shawn Laubach 1 , Willem Visser 2 , Hongjun Zheng 1 Kansas State University 1 NASA Ames Research Center/RIACS 2.
E N D
Tool-supported Program Abstraction for Finite-state Verification Matthew Dwyer1, John Hatcliff1, Corina Pasareanu1, Robby1, Roby Joehanes1, Shawn Laubach1, Willem Visser2, Hongjun Zheng1 Kansas State University1 NASA Ames Research Center/RIACS2 http://www.cis.ksu.edu/santos/bandera
OK Finite-state system Verification tool or Error trace (F W) Line 5: … Line 12: … Line 15:… Line 21:… Line 25:… Line 27:… … Line 41:… Line 47:… Specification Finite-state Verification
Finite-state Verification • Effective for analyzing properties of hardware systems Widespread success andadoption in industry • Recent years have seen many efforts to apply those techniques to software Limited success due to the enormous state spaces associated with most software systems
symbolic state represents a set of states Original system Abstract system abstraction Safety: The set of behaviors of the abstract system over-approximates the set of behaviors of the original system Abstraction: the key to scaling up
Goals of our work … Develop multiple forms of tool support for abstraction that are … … applicable to program source code … largely automated … usable by non-experts Evaluate the effectiveness of this tool support through… … implementation in the Bandera toolset … application to real multi-threaded Java programs
Requirement: Application processes are guaranteed to be scheduled for their budgeted time during a scheduling unit Case Study: DEOS Kernel (NASA Ames) Honeywell Dynamic Enforcement Operating System (DEOS) • A real-time operating system for integrated modular avionics systems • Non-trivial concurrent Java program: 1443 lines of code, 20 classes, 6 threads • With a known bug
class Thread Environment class Scheduler User Process 1 User Process 2 class StartofPeriodEvent class ListofThreads DEOS Architecture DEOS Kernel Requirement Monitor ... if(...) assert(false); ... ... System Clock & Timer
Verification of DEOS • We used Bandera and Java PathFinder (JPF) • Verification of the system exhausted 4 Gigabytes of memory without completing • no information about satisfaction of requirement • To verify property or produce a counter-example • to reduce the state space to a tractable size • some form of abstraction is needed
int (n<0) : NEG (n==0): ZERO (n>0) : POS Signs Signs x = ZERO; if (Signs.eq(x,ZERO)) x = Signs.add(x,POS); NEG ZERO POS Data Type Abstraction Collapses data domains via abstract interpretation: Code Data domains int x = 0; if (x == 0) x = x + 1;
DEOS Kernel class Thread int itsLastExecution; ... public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... } Environment User Process 1 User Process 2 class StartofPeriodEvent int itsPeriodId = 0; ... public int currentPeriod() { return itsPeriodId; } public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... } Variable Selection Control dependencies: 29 conditionals 16 methods 32 variables Requirement Monitor ... if(...) assert(false); ... ... System Clock & Timer
DEOS Kernel class Thread int itsLastExecution; ... public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... } Environment User Process 1 User Process 2 class StartofPeriodEvent int itsPeriodId = 0; ... public int currentPeriod() { return itsPeriodId; } public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... } Variable Selection Control dependencies: 29 conditionals 16 methods 32 variables Requirement Monitor ... if(...) assert(false); ... ... System Clock & Timer
DEOS Kernel class Thread int itsLastExecution; ... public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... } Environment User Process 1 User Process 2 class StartofPeriodEvent int itsPeriodId = 0; ... public int currentPeriod() { return itsPeriodId; } public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... } Unbounded! Variable Selection Data dependencies Requirement Monitor ... if(...) assert(false); ... ... System Clock & Timer
DEOS Kernel class Thread int itsLastExecution; ... public void startChargingCPUTime(){ int cp=itsEvent.currentPeriod(); if(cp == itsLastExecution) { ... } Environment User Process 1 User Process 2 class StartofPeriodEvent int itsPeriodId = 0; ... public int currentPeriod() { return itsPeriodId; } public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=itsPeriodId + 1; ... } Attaching Abstract Types SIGNS SIGNS Requirement Monitor ... if(...) assert(false); ... SIGNS ... System Clock & Timer
DEOS Kernel class Thread Signs itsLastExecution; ... public void startChargingCPUTime(){ Signs cp=itsEvent.currentPeriod(); if(Signs.eq(cp,itsLastExecution)){ ... } Environment User Process 1 User Process 2 class StartofPeriodEvent Signs itsPeriodId = ZERO; ... public Signs currentPeriod() { return itsPeriodId; } public void pulseEvent(...) {... if(countDown == 0) { itsPeriodId=Signs.add(itsPeriodId ,POS);... } Code Transformation Requirement Monitor ... if(...) assert(false); ... ... System Clock & Timer
Verification of Abstracted DEOS • JPF completed the check • produced a 464 step counter-example • Does the counter-example correspond to a feasible execution? • difficult to determine • because of abstraction, we may get spurious errors • We re-ran JPF to perform a customized search • found a guaranteed feasible 318 step counter-example • After fixing the bug • the requirement was verified
Our hypothesis Abstraction of data domains is necessary Automated support for • Defining abstract domains (and operators) • Selecting abstractions for program components • Generating abstract program models • Interpreting abstract counter-examples will make it possible to • Scale property verification to realistic systems • Ensure the safety of the verification process
Bandera Abstraction Specification Language PVS Concrete Type Abstract Type Inferred Type Abstraction Definition Variable x int y int done bool count int BASL Compiler …. o Object b Buffer Program Abstracted Program Abstract Code Generator Abstraction in Bandera Signs Signs Signs bool Abstraction Library int …. Point Buffer
Automatic Generation Example: Start safe, then refine:+(NEG,NEG)={NEG,ZERO,POS} Forall n1,n2: neg?(n1) and neg?(n2) implies not pos?(n1+n2) Proof obligations submitted to PVS... Forall n1,n2: neg?(n1) and neg?(n2) implies not zero?(n1+n2) Forall n1,n2: neg?(n1) and neg?(n2) implies not neg?(n1+n2) Definition of Abstractions in BASL operator + add begin (NEG , NEG) -> {NEG} ; (NEG , ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS , ZERO) -> {POS} ; (POS , POS) -> {POS} ; (_,_) -> {NEG,ZERO,POS}; /* case (POS,NEG),(NEG,POS) */ end abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n < 0 -> {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end
Compiled Compiling BASL Definitions abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n < 0 -> {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end operator + add begin (NEG , NEG) -> {NEG} ; (NEG , ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS , ZERO) -> {POS} ; (POS , POS) -> {POS} ; (_,_)-> {NEG, ZERO, POS}; /* case (POS,NEG), (NEG,POS) */ end public class Signs { public static final int NEG = 0; // mask 1 public static final int ZERO = 1; // mask 2 public static final int POS = 2; // mask 4 public static int abs(int n) { if (n < 0) return NEG; if (n == 0) return ZERO; if (n > 0) return POS; } public static int add(int arg1, int arg2) { if (arg1==NEG && arg2==NEG) return NEG; if (arg1==NEG && arg2==ZERO) return NEG; if (arg1==ZERO && arg2==NEG) return NEG; if (arg1==ZERO && arg2==ZERO) return ZERO; if (arg1==ZERO && arg2==POS) return POS; if (arg1==POS && arg2==ZERO) return POS; if (arg1==POS && arg2==POS) return POS; return Bandera.choose(7); /* case (POS,NEG), (NEG,POS) */ }
Data Type Abstractions • Library of abstractions for base types contains: • Range(i,j),i..j modeled precisely, e.g., Range(0,0) is the signs abstraction • Modulo(k), Set(v,…) • Point maps all concrete values to unknown • User extendable for base types • Array abstractions • Specified by an index abstraction and an element abstraction • Class abstractions • Specified by abstractions for each field
Interpreting Results • For an abstracted program, a counter-example may be infeasible because: • Over-approximation introduced by abstraction • Example: x = -2; if(x + 2 == 0) then ... x = NEG; if(Signs.eq(Signs.add(x,POS),ZERO)) then ... {NEG,ZERO,POS}
Choose-free state space search • Theorem [Saidi:SAS’00] Every path in the abstracted program where all assignments are deterministic is a path in the concrete program. • Bias the model checker • to look only at paths that do not include instructions that introduce non-determinism • JPF model checker modified • to detect non-deterministic choice (i.e. calls to Bandera.choose()); backtrack from those points
State space searched Undetectable Violation Detectable Violation Choice-bounded Search choose() X X
Comparison to Related Work • Predicate abstraction (Graf/Saidi) • We use PVS to abstract operator definitions, not complete systems • We can reuse abstractions for different systems • Tool support for program abstraction • e.g., SLAM, JPF, Feaver • Abstraction at the source-code level • Supports multiple checking tools • e.g., JPF, Java Checker/Verisoft, FLAVERS/Java, … • Counter-example analysis • Theorem prover based (InVest) • Forward simulation (CMU)
Conclusions • Tool support for abstraction of base and array types enables verification of real properties of real programs • Extend support for objects • Heap abstractions tohandle an unbounded number of dynamically allocated objects • Extend automation • Automated selection and refinement based on counter-example analysis