bandera tool set presented by: dor nir. outline specification language (ltl) software verification...
Post on 21-Dec-2015
212 views
TRANSCRIPT
Bandera Tool Set
Presented by: Dor Nir
Outline
Specification Language (LTL) Software verification problems Introduction to Bandera tool Set Bandera Specification Language (BSL) Data Type Abstraction Slicing Results and conclusions
The Vision
Automatic Verifier
SourceCode
Requirements
ProgramApproved
Counter exampleUse case
Formal SystemSpecification
Specification Languages
Linear Temporal Logic (LTL) Computation Tree Logic (CTL, CTL*) Excplicit Clock Temporal Logic
(XCTL) Temporal Logic of Actions (TLA,
TLA+) Interval Temporal Logic (ITL)
Propositional Linear Temporal Logic
O(p) – next p – always ◊p – eventually pUq – Until pWq – pUq V ٱp
P
PP P P
P
PP P P q
Notation: p => q ≡ ٱ(pq)
Some typical property patterns
Recurrence ◊p infinitely often ◊p eventually alwaysPrecendence pU(qUr) p* q* r (pUq)Ur (p*q)* r ¬pWq p cannot occur before q
r P q
Mutual Exclusion Properties
• Resource is never owned by P1 and P2, simultaneously
(P1_ownP2_own)
• Whenever P1 has requested the resource it will eventually get it
(P1_reqP1_own)
• If P1 requests the resource infinitely often (when the resource is free then it will infinitely often get it (strong fairness)
(P1_req (P1_ownP2_own)) P1_own
Finite-state Verification
OKFinite-state system
Specification
Verification tool
or
Error trace
Line 5: …Line 12: …Line 15:…Line 21:…Line 25:…Line 27:… …Line 41:…Line 47:…
Finite-state Verification Effective for analyzing properties
of hardware systems
Controllertrain-in train-out
go,stop close,
openposition
Widespread success andadoption in industry
Software verification
Limited success due to the enormous state spaces
associated with most software systems
Recent years have seen many efforts to apply those techniques to software
Abstraction: the key to scaling up
Originalsystem
symbolic state
Abstract system
represents a set of states
abstraction
Safety: The set of behaviors of the abstract system over-approximates the set of behaviors of the original system
Goals…
•Verification tool for software, using abstraction.
•Easy for writing specifications.•Use of existing verification tools.•Verification time is reasonable.•Easy to understand the counter example.•Reusable. (Specifications)
Bandera: An open tool set for model-checking Java source
code
Checker Inputs
CheckerOutputs
Optimization Control
Transformation &Abstraction Tools
ModelCheckers
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Temporal Specification
Graphical User Interface
Error Trace Mapping
Bandera
Slicing
AbstractInterpretation
Static Analysis
?
Issue: Rendering Requirement
Often difficult to formalize a requirement in temporal logic
“Between the window open and the window close, button X can be pushed at most twice.”
[]((open && <>close) -> ((!pushX && !close) U (close || ((pushX && !close) U (close || ((!pushX && !close) U (close || ((pushX && !close) U (close || (!pushX U close))))))))))
…is rendered in LTL as...
Graphical User InterfaceIssue: Checker Dependence
Checker Inputs
Transformation &Abstraction Tools
ModelCheckers
Java Source
void add(Object o) { buffer[head] = o; head = (head+1)%size;}
Object take() { … tail=(tail+1)%size; return buffer[tail];}
Temporal Specification
Bandera
LTL
LTL
Spin
CTL
SMV
CSP
FDR
mismatch!
Issue: Representation Dependence
Source’s representation
(((_collect(heap_b) == 1)\ && (BoundedBuffer_col.instance[_index(heap _b)].head == BoundedBuffer_col.instance[_index(heap _b)].tail) )\ || ((_collect(heap _b) == 3)\ && (BoundedBuffer_col_0.instance[_index(heap _b)].head == BoundedBuffer_col_0.instance[_index(heap _b)].tail) )\ || ((_collect(heap _b) == 0) && TRAP))
Heap.b.head == Heap.b.tail Model’s representation
Problem summary
Rendering Checker dependence Representation dependence Quantification
BSL: Bandera Specification Language
Assertion DefinitionPredicate Definition
Assertion PropertySpecification
(selective enabling)
Temporal PropertySpecification
(via pattern language)Quantification
Propositions stated in terms of source code features
Based on an extensible system of temporal specification patterns
Heap objects are named via object quantification
Predicate Forms Static/Instance Data Constraints
@observable [static] EXP <name> <exp>;
Invocation
@observable INVOKE <name> <exp>;
Return
@observable RETURN <name> <exp>;
Arbitrary Locations
@observable LOCATION[<label>] <name> <exp>;
Semantic Issues
o1.next.value == 0
(o1 != null) && (o1.next != null) && ( )
Quantification (Cont’d)
forall[b:BoundedBuffer]. {Full(b)} leads to {!Full(b)} globally;
(heap.b == null U (heap.b != null && ([](heap.b.head == heap.b.tail) -> <>(heap.b.head != heap.b.tail))))|| [](heap.b == null)
Methodology: Property Specification
Identify observables (propositions) in requirement
Define propositions in source Java-doc comments
Use GUI to select appropriate temporal pattern
parameterized by declared observables
Add quantification if property contains instance
propositions.
Given a software requirement...
Bounded Buffer class BoundedBuffer { Object [] buffer; int head; /* next available slot */ int tail; /* last available slot */ int bound; /* max # of elements */
public BoundedBuffer(int b) {…}
public synchronized boolean isEmpty() {…}
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
Initialization
head tail
Add,Add
head tail
Add,Take,Take
headtail
Bounded Buffer
public BoundedBuffer(int b) { bound = b; buffer = new Object[bound]; head = 0; tail = bound-1; }
public synchronized boolean isEmpty() { return head == ((tail+1) % bound); }
Initialization
head tail
Add,Add
head tail
Add,Take,Take
headtail
Bounded Buffer public synchronized void add(Object o) { while ( tail == head ) try { wait(); } catch (InterruptedException ex) {}
buffer_[head] = o; head = (head+1) % bound; notifyAll(); }
public synchronized Object take() { while (head == ((tail+1) % bound)) try { wait(); } catch (InterruptedException ex) {}
tail = (tail+1) % bound; notifyAll(); return buffer_[tail]; }
Initialization
head tail
Add,Add
head tail
Add,Take,Take
headtail
Bounded Buffer Properties Full buffers eventually become
non-full Indices always stay in range Empty buffers must be added
to before being taken from Buffers are constructed with
positive bounds
Property Specification
class BoundedBuffer { Object [] buffer; int head, tail, bound;
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
Requirement 1:
If a buffer becomes full,it will eventually becomenon-full.
/** * @observable * EXP Full: (head == tail); */
Bandera Specification:
FullToNonFull: {!Full(b)} responds to {Full(b)} globally;
forall[b:BoundedBuffer].
Property Specification
class BoundedBuffer { Object [] buffer; int head, tail, bound;
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
Requirement 2:
/** * @observable * EXP HeadRange: * head >= 0 && head < bound; * Exp TailRange: * tail >= 0 && tail < bound; */
Indices always stay in range.
Bandera Specification:
IndexRangeInvariant: {HeadRange(b) && TailRange(b)} is universal globally;
forall[b:BoundedBuffer].
Property Specification
Requirement 3:
Empty buffers must added to before being taken from
Bandera Specification:
NoTakeWhileEmpty: {take.Return(b)} is absent after {Empty(b)} until {add.Call(b)};
forall[b:BoundedBuffer].
/** * @observable * EXP Empty: * head == ((tail+1) % bound);*/class BoundedBuffer { int head, tail, bound;
public synchronized void add(Object o) {…}
public synchronized Object take () {…}}
/** * @observable INVOKE Call; */
/** * @observable RETURN Return; */
Property Specification
Requirement 4:
Bandera Specification:
PositiveBound: enable assertions {PositiveBound};
Buffers are constructed with positive bounds
public BoundedBuffer(int b) { bound = b; buffer = new Object[bound]; head = 0; tail = bound-1;}
/** * @assert * PRE PositiveBound: * (b > 0);*/
Quantificationforall[b:BoundedBuffer].P(b)
Solution
Quantified set is not fixed varies within executions varies across executions
by adding a state variable (for b) that will eventually be bound non-deterministically to each instance
by enabling checking of the formula only when variable is bound to an instance
Data Type Abstraction
int x = 0;if (x == 0) x = x + 1;
Data domains
(n<0) : NEG(n==0): ZERO(n>0) : POS
Signs
NEG POSZERO
int
Code
Signs x = ZERO;if (Signs.eq(x,ZERO)) x = Signs.add(x,POS);
Collapses data domains via abstract interpretation:
Bandera hypothesis Abstraction of data domains is necessaryAutomated 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
Abstraction in Bandera
AbstractionLibrary
BASLCompiler
VariableConcrete Type
Abstract Type
Inferred Type
Object
xydonecount
ob
intintbool
Buffer
int….
SignsSignsSigns
intbool
….PointBuffer
Program Abstract CodeGenerator
AbstractedProgram
BanderaAbstractionSpecificationLanguage
AbstractionDefinition
PVS
Definition of Abstractions in BASLabstraction Signs abstracts intbegin 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
AutomaticGeneration
Forall n1,n2: neg?(n1) and neg?(n2) implies not pos?(n1+n2)
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)
Proof obligations submitted to PVS...
Example: Start safe, then refine: +(NEG,NEG)={NEG,ZERO,POS}
Compiling BASL Definitionsabstraction Signs abstracts intbegin 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) */ }
Compiled
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
Example:x = -2; if(x + 2 == 0) then ...x = NEG; if(Signs.eq(Signs.add(x,POS),ZERO)) then ...
{NEG,ZERO,POS}
For an abstracted program, a counter-example may be infeasible because:– Over-approximation introduced by abstraction
Slicing
Generate reduced model Program P with specification Φ Bandera collect statements of
interest From Φ (slicing criterion for Φ) Compute P’: reduce version of P. P |= Φ P’|= Φ
Slicing
Does program dependence-based slicing to get a reduced version of P dependences: data, control, interference, ready,
wait backwards slicing
Effectiveness based on structure of program
Relevant
In Property
Counter-Example: Overview
Counter-example with a thousand states?!?!
Bandera provides debugger-like features: map states to source code program tracing create checkpoints keep track of variables and objects UML-like object displays lock graphs
Using Bandera
• Launch the Bandera User Interface (BUI) from the command line
• Future runs: save which components you want to use in session files
Counter-Example:Program Tracing
Counter-Example:Lock Graph
Counter-Example:Object Viewer
Property Specification
Property Specification
Mandatory Performance Slide
Problem ExtractTime (s)
CheckTime (s)
CheckResult
States
b, r1, n 24 2674 true 7338120
b, r1, s 13 4 true 3478
b, r1, a 15 4 true 895
b, r2, s 13 56 true 528059
b, r2, a 16 11 true 27519
b, p1, s 13 4 true 2507
b, p1, a 15 4 true 331
d, r1, s 13 3 false 88
d, r1, a 15 2 false 17
Threaded Pipeline
b: basicd: defective variant
r: response propertyp: precedence property
n: no reductionss: slicinga: slicing + data abstraction
BoundedBuffer Propery Check Data
Property Sliced
Never-Claim States
States Stored
Buffer Assertions Yes - 17797
IndexRangeInv Yes 14 45215
IndexRangeInv,Buffer Assertions
Yes 14 115387
Full To Non Full Yes 25 64687
Full to Non Full,Buffer Assertions
Yes 25 154842
When to Use Model Checking
Control-related properties assertions pre- and post-conditions simple data invariants
Container objects Stacks Queues
Verifying concurrent behavior Necessity for counter-examples Automatic property verification of source
code
Analysis Not Appropriate for Model Checking Data-related properties
Verification of sorting algorithms Use other formal methods instead (theorem
proving)
Where static dataflow analysis is better array-bounds errors buffer overruns null-pointer de-referencing
Conclusions
Software verification is applicable and can help. (but…)
Slicing is critical. BSL making the specification
writing much more simple. (but…) The counter example is intuitive.
Future work
More quantifications (array) Support predicate with arbitrary
parameters Method invocation in predicate. More model checkers. Increase the template library