Upload
qiana
View
30
Download
0
Embed Size (px)
DESCRIPTION
Cooperative Reasoning for Automatic Software Verification. Andrew Ireland School of Mathematical & Computer Sciences Heriot-Watt University Edinburgh. Outline. Cooperative reasoning: Tight integration of complementary techniques Compensating for each other’s weaknesses - PowerPoint PPT Presentation
Citation preview
© Andrew IrelandDependable Systems Group
Cooperative Reasoning for Automatic Software Verification
Andrew IrelandSchool of Mathematical & Computer Sciences
Heriot-Watt UniversityEdinburgh
© Andrew IrelandDependable Systems Group
Outline
• Cooperative reasoning:• Tight integration of complementary techniques• Compensating for each other’s weaknesses
• Proof planning & cooperative reasoning:• Decouples proof search & proof checking• Promotes a flexible style of proof discovery
• Case studies:• Property based verification• Functional verification
© Andrew IrelandDependable Systems Group
Proof Planning
Proof planningMethods + Critics
Proof checkingTactics
Conjectures Theory
Proof plans promote reuse, flexibility and cooperation
© Andrew IrelandDependable Systems Group
Flexibility?• Conjecture:
∀l:list(A).rotate(length(l),l)=l• Speculative generalization:
∀l,a:list(A).
rotate(length(l),F1(l,a))= F2(l,a)
• Generalized conjecture:
∀l,a:list(A). rotate(length(l),app(l,a))=app(a,l)
Proof planning promotes the productive use of failure,
and in particular middle-out reasoning (MOR)
© Andrew IrelandDependable Systems Group
The SPARK Approach• A subset of Ada that eliminates potential ambiguities
and insecurities (PRAXIS) • Expressive enough for industrial applications, but
restrictive enough to support rigorous analysis• SPARK toolset supports data & information flow
analysis and formal verification• Partial correctness & exception freedom proof, e.g.
proving code is free from buffer overflows, range violations, division by zero.
• Avionics, transportation, air traffic control, security,…
© Andrew IrelandDependable Systems Group
The SPARK ApproachSPARK
ExaminerSPADE Simplifier
SPADEProof Checker
VCs
Cmds
UnprovenVCs
SPARK
codeProofs
© Andrew IrelandDependable Systems Group
subtype AR_T is Integer range 0..9; type A_T is array (AR_T) of Integer; ... procedure Filter(A: in A_T; R: out Integer) is begin R:=0; for I in AR_T loop if A(I)>=0 and A(I)<=100 then R:=R+A(I); end if; end loop; end Filter;
A Filter Example
R:=R+A(I);
If R <= Integer’Last then potential overflow exception
© Andrew IrelandDependable Systems Group
subtype AR_T is Integer range 0..9; type A_T is array (AR_T) of Integer; ... procedure Filter(A: in A_T; R: out Integer) is begin R:=0; for I in AR_T loop --# assert R >= 0 and R <= I*100 if A(I)>=0 and A(I)<=100 then R:=R+A(I); end if; end loop; end Filter;
Loop Invariant
© Andrew IrelandDependable Systems Group
The SPARK ApproachSPARK
ExaminerSPADE Simplifier
SPADEProof Checker
VCs
Cmds
UnprovenVCs
SPARK
codeProofs
© Andrew IrelandDependable Systems Group
NuSPADE ProjectSPARK
ExaminerSPADE Simplifier
SPADEProof Checker
• Bill J. Ellis • EPSRC Critical Systems programme (GR/R24081)• EPSRC RAIS Scheme (GR/T11289)• http://www.macs.hw.ac.uk/nuspade
VCs
Cmds
UnprovenVCs
Refinement
SPADEase
SPARKcode
Proofs
© Andrew IrelandDependable Systems Group
SPADEase
Program Analysis
Proof Planning
• Proof planning: • automates invariant & exception freedom proofs • supports equational reasoning • generates program property schemas (invariants)
• Program analysis: • instantiates program property schemas (invariants)• generates equational reasoning goals
© Andrew IrelandDependable Systems Group
Loop Invariant VCH1: r >= 0 .
H2: r <= loop__1__i * 100 .
...
H6: element(a, [loop__1__i]) >= 0 .
H7: element(a, [loop__1__i]) <= 100 .
…
->
C1: r + element(a,[loop__1__i]) >= 0 .
C2: r + element(a,[loop__1__i]) <= (loop__1__i + 1) * 100 .
…
© Andrew IrelandDependable Systems Group
Loop Invariant VCH1: r >= 0 .
H2: r <= loop__1__i * 100 .
...
H6: element(a, [loop__1__i]) >= 0 .
H7: element(a, [loop__1__i]) <= 100 .
…
->
C1: r + element(a,[loop__1__i]) >= 0 .
C2: r + element(a,[loop__1__i]) <= (loop__1__i + 1) * 100 .
…
Rippling
© Andrew IrelandDependable Systems Group
Rippling Proof Pattern
Given:
Goal: f(g(c1(v)), h(u))
∀u’. f(g(v), h(u’))
© Andrew IrelandDependable Systems Group
Rippling Proof Pattern
Given:
Goal:
Rippling = difference identification + reduction
∀u’. f(g(v), h(u’))
f(g(c1(v)), h(u))
c2(f(g(v), h(c3(u))))
© Andrew IrelandDependable Systems Group
Separation Logic • John Reynolds (CMU) and Peter O’Hearn (QMU)• Simplifies pointer program proofs by enriching
Hoare logic with spatial operators• Builds upon the logic of bunched implications
(O’Hearn & Pym), and early work by Burstall• Focuses the reasoning effort on only those parts
of the heap that are relevant to a program unit, i.e. local reasoning
© Andrew IrelandDependable Systems Group
Modelling the Heap
• Empty heap: the assertion emp holds for a heap that contains no cells
• Singleton heap: the assertion X E↦ holds for a heap that contains a single cell (maps-to relation), e.g.
5i
(i 5)↦
© Andrew IrelandDependable Systems Group
Separating Conjunction P*Q holds for a heap if the heap can be divided
into two disjoint heaplets H1 and H2, such that P holds for H1 holds for Q holds for H2, e.g.
5i
(i 5,7)↦
7
(i 5)*(i+1 7)↦ ↦(i↪ 5,7)
(i 5)*(i+1 7)↦ ↦
5i7
*true
© Andrew IrelandDependable Systems Group
Separating Implication P Q asserts that, if the current heap H1 is
extended with a disjoint heaplet H2 in which P holds, then Q will hold in the extended heap, e.g.
i
(i 5,7) Q↦ Q
5i7
*
*
© Andrew IrelandDependable Systems Group
Singly-linked Lists
list([],Y,Z)↔ emp Y=Zlist([W|X],Y,Z)↔(∃p.(Y ↦ W,p)*list(X,p,Z))
a1 a2 an…i
list([a1, a2, …, an],i,j)
j
© Andrew IrelandDependable Systems Group
{∃A. list(A,i,nil)∧ A0 = A} j := nil;{R} while not(i = nil) loop k := [i+1]; [i+1] := j; j := i; i := k end loop{∃B.list(B,j,nil) ∧ A0 = rev(B)}
Loop Invariant Discovery
R:{∃A,B.list(A,i,nil)*list(B,j,nil)∧ A0 = app(rev(B),A)}
© Andrew IrelandDependable Systems Group
{∃A. list(A,i,nil)∧ A0 = A} j := nil;{R} while not(i = nil) loop k := [i+1]; [i+1] := j; j := i; i := k end loop{∃B.list(B,j,nil) ∧ A0 = rev(B)}
Loop Invariant Discovery
R:{∃A,B.list(A,i,nil)*list(B,j,nil)∧ A0 = app(rev(B),A)}
shape
© Andrew IrelandDependable Systems Group
{∃A. list(A,i,nil)∧ A0 = A} j := nil;{R} while not(i = nil) loop k := [i+1]; [i+1] := j; j := i; i := k end loop{∃B.list(B,j,nil) ∧ A0 = rev(B)}
Loop Invariant Discovery
R:{∃A,B.list(A,i,nil)*list(B,j,nil)∧ A0 = app(rev(B),A)}
structural
© Andrew IrelandDependable Systems Group
{∃A. list(A,i,nil)∧ A0 = A} j := nil;{R} while not(i = nil) loop k := [i+1]; [i+1] := j; j := i; i := k end loop{∃B.list(B,j,nil) ∧ A0 = rev(B)}
Loop Invariant Discovery
R:{∃A,B.list(A,i,nil)*list(B,j,nil)∧ A0 = app(rev(B),A)}
functional
© Andrew IrelandDependable Systems Group
Verification Condition( A∃ ’,B’.list(A’,i,nil)*list(B’,j,nil) ∧ A0
= app(rev(B’),A’)) (i∧ ≠nil)
├
( X∃ 2.( X,Y.(i X,Y)*((i X,j) ∃ ↦ ↦ ( A,B.list(A,X∃ 2,nil)*list(B,i,nil) ∧A0 = app(rev(B),A)))) ( X∧ ∃ 1.(i X↪ 1,X2)))
*
Case-splittingMutatingRippling
© Andrew IrelandDependable Systems Group
Given: Loop Invariant
xn+1 xn+2 xw…nil
xn xn-1 x1…nil
( A∃ ’,B’.list(A’,i,nil)*list(B’,j,nil) A∧ 0 = app(rev(B’),A’)) (i∧ ≠nil)
i
j
© Andrew IrelandDependable Systems Group
xn+1 xn+2 xw…inil
xn xn-1 x1…jnil
( X∃ 2.( X,Y.(i X,Y)*((i X,j) ∃ ↦ ↦ ( A,B.list(A,X∃ 2,nil)*list(B,i,nil)
A∧ 0 = app(rev(B),A)) ( X∧ ∃ 1.(i X↪ 1,X2)))
*
Goal: Weakest Precondition x2
© Andrew IrelandDependable Systems Group
Case-splitting & Mutating
xn+1 xn+2 xw…nil
xn xn-1 x1…nil
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev([xn+1|Btl]),A))
i
j
© Andrew IrelandDependable Systems Group
Goal: … (U ↦ V,W) (( … ) (U’ ↦ V’,W’) ( … ))
* * *
Mutating Proof Pattern
© Andrew IrelandDependable Systems Group
Mutating Proof Pattern
Goal: … (U ↦ V,W) (( … ) (U’ ↦ V’,W’) ( … ))
… (U ↦ V,W) ((U’ ↦ V’,W’) (( … ) (…)))
*
((…) ( …))
Mutating = reconcile complementary heaplets
X (X Y) Y *(rewrite rule)
* * *
* *
* *
© Andrew IrelandDependable Systems Group
Rippling ( A’,B’.list(A’,i,nil)*list(B’,j,nil) ∃ A∧ 0 = app(rev(B’),A’)) (i≠nil)∧├
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil) ∧A0 = app(rev([xn+1|Btl]),A))
© Andrew IrelandDependable Systems Group
Rippling ( A’,B’.list(A’,i,nil)*list(B’,j,nil) ∃ A∧ 0 = app(rev(B’),A’)) (i≠nil)∧├
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev([xn+1|Btl]),A))
© Andrew IrelandDependable Systems Group
Rippling ( A’,B’.list(A’,i,nil)*list(B’,j,nil) ∃ A∧ 0 = app(rev(B’),A’)) (i≠nil)∧├
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev([xn+1|Btl]),A))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(app(rev(Btl),[xn+1]),A))
© Andrew IrelandDependable Systems Group
Rippling ( A’,B’.list(A’,i,nil)*list(B’,j,nil) ∃ A∧ 0 = app(rev(B’),A’)) (i≠nil)∧├
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev([xn+1|Btl]),A))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(app(rev(Btl),[xn+1]),A))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev(Btl),app([xn+1],A)))
© Andrew IrelandDependable Systems Group
Rippling ( A’,B’.list(A’,i,nil)*list(B’,j,nil) ∃ A∧ 0 = app(rev(B’),A’)) (i≠nil)∧├
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev([xn+1|Btl]),A))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(app(rev(Btl),[xn+1]),A))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev(Btl),app([xn+1],A)))
( A,B∃ tl.list([xn+1|A],i,nil)*list(Btl,j,nil)
A∧ 0 = app(rev(Btl),[xn+1|,A]))
© Andrew IrelandDependable Systems Group
CORE system
Smallfoot (family)
IsaPlanner
Spec &code
ProofsIsabelle
animation
• Ewen Maclean, Gudmund Grov, Richard Addison• EPSRC (EP/F037597) http://www.macs.hw.ac.uk/core• Smallfoot (O’Hearn’s Theory Group)• IsaPlanner (Bundy’s Mathematical Reasoning Group)
CORE Project
© Andrew IrelandDependable Systems Group
CORE Project
Shape Analysis
Proof Planning
Term Synthesis
• Shape analysis automates:• checking of shape properties • shape invariant generation
• Proof planning automates proof search: • structural properties• functional properties
• Term synthesis automates invariant discovery – ongoing work (alternative to MOR)
© Andrew IrelandDependable Systems Group
Invariant Discovery (Ongoing)∃A,B. list(V1,i,nil)*
list(V2,j,nil)∧ A0 = F1(rev(B),A,B)
© Andrew IrelandDependable Systems Group
∃A,B. list(V1,i,nil)*
list(V2,j,nil)∧ A0 = F1(rev(B),A,B)
Invariant Discovery (Ongoing)
Shape
Shape invariants currently hand-crafted, but aiming for automation via Smallfoot family.
© Andrew IrelandDependable Systems Group
∃A,B. list(V1,i,nil)*
list(V2,j,nil)∧ A0 = F1(rev(B),A,B)
Invariant Discovery (Ongoing)
Structural
Structural invariants generated via MOR (proof planning within CORE System)
© Andrew IrelandDependable Systems Group
∃A,B. list(V1,i,nil)*
list(V2,j,nil)∧ A0 = F1(rev(B),A,B)
Invariant Discovery (Ongoing)
Functional invariants generated via term synthesis (CORE System) and proved via proof planning (IsaPlanner)
Functional
© Andrew IrelandDependable Systems Group
Conclusion
• Successful software verification approaches are typically an integration of techniques
• Argued for cooperative reasoning, i.e. a tight integration of complementary techniques
• Focused on proof planning as a flexible approach to proof automation that promotes cooperative reasoning
© Andrew IrelandDependable Systems Group