Deductive Program Verification Jean-Christophe Filli atre CNRS - - PowerPoint PPT Presentation

deductive program verification
SMART_READER_LITE
LIVE PREVIEW

Deductive Program Verification Jean-Christophe Filli atre CNRS - - PowerPoint PPT Presentation

Deductive Program Verification Jean-Christophe Filli atre CNRS ITP 2018 Oxford, UK July 12, 2018 1 / 32 joint work with Fran cois Bobot Claude March e Guillaume Melquiond Andrei Paskevich 2 / 32 a question for programmers


slide-1
SLIDE 1

Deductive Program Verification

Jean-Christophe Filliˆ atre CNRS ITP 2018

Oxford, UK July 12, 2018

1 / 32

slide-2
SLIDE 2

joint work with

Fran¸ cois Bobot Claude March´ e Guillaume Melquiond Andrei Paskevich

2 / 32

slide-3
SLIDE 3

a question for programmers

shall I be pure or impure?

3 / 32

slide-4
SLIDE 4

a question for program verifiers

shall I be pure or impure?

4 / 32

slide-5
SLIDE 5

a question for program verifiers

shall I be pure or impure? FP mutability feast

slide-6
SLIDE 6

a question for program verifiers

shall I be pure or impure? FP mutability feast

the While language

slide-7
SLIDE 7

a question for program verifiers

shall I be pure or impure? FP mutability feast

the While language

WhyML

4 / 32

slide-8
SLIDE 8

WhyML

goal no model of the heap to get simpler VCs solution records with mutable fields + static control of aliases

5 / 32

slide-9
SLIDE 9

mutable variables aka references

type ref ’a = { mutable contents: ’a; }

6 / 32

slide-10
SLIDE 10

we can model some data structures

e.g. arrays type array ’a = private { mutable ghost elts: int -> ’a; length: int; }

7 / 32

slide-11
SLIDE 11

we can nest mutable types

e.g. a heap in a resizeable array type heap = { mutable data: array elt; mutable size: int; mutable ghost view: bag elt; } the type checker is powerful enough to let you replace the data field while keeping track of aliases

[ESOP 2013]

8 / 32

slide-12
SLIDE 12

the key is abstraction

there are mutable DS you cannot implement (e.g. linked lists, mutable trees) yet you can model them easily then you can verify client code, thanks to proof modularity

9 / 32

slide-13
SLIDE 13

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool

10 / 32

slide-14
SLIDE 14

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x

10 / 32

slide-15
SLIDE 15

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y

10 / 32

slide-16
SLIDE 16

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z

10 / 32

slide-17
SLIDE 17

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z

10 / 32

slide-18
SLIDE 18

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z u

10 / 32

slide-19
SLIDE 19

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z u

10 / 32

slide-20
SLIDE 20

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z u v

10 / 32

slide-21
SLIDE 21

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z v u

10 / 32

slide-22
SLIDE 22

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z v u w

10 / 32

slide-23
SLIDE 23

example: union-find

type elem val make : unit -> elem val union: elem -> elem -> unit val find : elem -> elem val same : elem -> elem -> bool x y z v u w

10 / 32

slide-24
SLIDE 24

example: union-find

type elem type uf = { mutable dom: set elem; mutable rep: elem -> elem; } val ghost create () : uf val make (ghost uf: uf) () : elem val union (ghost uf: uf) (x y: elem) : unit val find (ghost uf: uf) (x : elem) : elem val same (ghost uf: uf) (x y: elem) : bool

11 / 32

slide-25
SLIDE 25

what else

WhyML features

  • polymorphism
  • algebraic data types, pattern matching
  • exceptions, break, continue, return
  • ghost code and ghost data

[CAV 2014]

  • contracts, loop and type invariants
  • VCGen = either traditional or Flanagan/Saxe style WP

12 / 32

slide-26
SLIDE 26

a logic for program verification

goal rich enough to make your life easier, simple enough to be sent to ATPs

13 / 32

slide-27
SLIDE 27

a logic for program verification

goal rich enough to make your life easier, simple enough to be sent to ATPs

  • ur solution

a total, polymorphic first-order logic with

  • algebraic types & pattern matching
  • recursive definitions
  • (co)inductive predicates
  • mapping type α → β, λ-notation, application

[FroCos 2011, CADE 2013, VSTTE 2014]

13 / 32

slide-28
SLIDE 28

Why3

WhyML Why3 logic

slide-29
SLIDE 29

Why3

WhyML Why3 logic

Z3 Alt-Ergo CVC4 ... ...

slide-30
SLIDE 30

Why3

WhyML Why3 logic

Z3 Alt-Ergo CVC4 ... ... OCaml C

slide-31
SLIDE 31

Why3

WhyML Why3 logic

Z3 Alt-Ergo CVC4 ... ... OCaml C C Java Ada

slide-32
SLIDE 32

Why3

WhyML Why3 logic

Z3 Alt-Ergo CVC4 ... ... OCaml C C Java Ada your language

slide-33
SLIDE 33

Why3

WhyML Why3 logic

Z3 Alt-Ergo CVC4 ... ... OCaml C C Java Ada your language your VCs

14 / 32

slide-34
SLIDE 34

using off-the-shelf provers

Why3 currently supports 25+ ITPs and ATPs for each prover, a special “driver” file controls

[Boogie 2011]

  • logical transformations to apply
  • input/output format
  • predefined symbols, axioms to be removed

15 / 32

slide-35
SLIDE 35

example: Z3 driver

printer "smtv2" valid "^unsat" invalid "^sat" transformation "inline trivial" transformation "eliminate builtin" transformation "eliminate definition" transformation "eliminate inductive" transformation "eliminate algebraic" transformation "simplify formula" transformation "discriminate" transformation "encoding smt" prelude "(set-logic AUFNIRA)" theory BuiltIn syntax type int "Int" syntax type real "Real" syntax predicate (=) "(= %1 %2)" end ...

16 / 32

slide-36
SLIDE 36

demo

union-find

joint work with S. Melo de Sousa, M. Pereira, and M. Clochard

17 / 32

slide-37
SLIDE 37

API

type elem type uf = ... val ghost create () : uf val make (ghost uf: uf) () : elem val union (ghost uf: uf) (x y: elem) : unit val find (ghost uf: uf) (x : elem) : elem val same (ghost uf: uf) (x y: elem) : bool

18 / 32

slide-38
SLIDE 38

specification

type elem type uf = { mutable dom: set elem; mutable rep: elem -> elem; } invariant { forall x. mem x dom -> mem (rep x) dom && rep (rep x) = rep x } val ghost create () : uf ensures { result.dom = empty }

19 / 32

slide-39
SLIDE 39

specification

val make (ghost uf: uf) () : elem writes { uf.dom, uf.rep } ensures { not (mem result (old uf.dom)) } ensures { uf.dom = add result (old uf.dom) } ensures { uf.rep = (old uf.rep)[result <- result] } val find (ghost uf: uf) (x: elem) : elem requires { mem x uf.dom } ensures { result = uf.rep x }

20 / 32

slide-40
SLIDE 40

specification

val union (ghost uf: uf) (x y: elem) : ghost elem requires { mem x uf.dom } requires { mem y uf.dom } writes { uf.rep } ensures { result = old (uf.rep x) || result = old (uf.rep y) } ensures { forall z. mem z uf.dom -> uf.rep z = if old (uf.rep z = uf.rep x || uf.rep z = uf.rep y) then result else old (uf.rep z) }

21 / 32

slide-41
SLIDE 41

implementation

type elem = content ref and content = | Link of elem | Root of int

22 / 32

slide-42
SLIDE 42

implementation

type elem = content ref and content = | Link of elem | Root of int x 0

22 / 32

slide-43
SLIDE 43

implementation

type elem = content ref and content = | Link of elem | Root of int x 0 y 0

22 / 32

slide-44
SLIDE 44

implementation

type elem = content ref and content = | Link of elem | Root of int x 0 y 0 z 0

22 / 32

slide-45
SLIDE 45

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z 0

22 / 32

slide-46
SLIDE 46

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z 0 u 0

22 / 32

slide-47
SLIDE 47

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z u 0

22 / 32

slide-48
SLIDE 48

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z u 0 v 0

22 / 32

slide-49
SLIDE 49

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z v 1 u

22 / 32

slide-50
SLIDE 50

implementation

type elem = content ref and content = | Link of elem | Root of int x 1 y z v 1 u w 0

22 / 32

slide-51
SLIDE 51

implementation

type elem = content ref and content = | Link of elem | Root of int x 2 y z v u w 0

22 / 32

slide-52
SLIDE 52

implementation

type elem = content ref and content = | Link of elem | Root of int x 2 y z v u w 0 let’s verify this with Why3

22 / 32

slide-53
SLIDE 53

Why3 implementation

too complex for Why3’s type checker; let’s model the heap type elem = content ref and content = | Link of elem | Root of int type loc type elem = loc type content = | Link loc | Root Peano.t type heap = { ghost mutable refs: loc -> option content; }

23 / 32

slide-54
SLIDE 54

termination

24 / 32

slide-55
SLIDE 55

termination

it would be very tempting to introduce an inductive notion of path inductive path (h: heap) (x y: elem) = | Path0: forall x y k. h.refs x = Some (Root k) -> path h x x | Path1: forall x y z. h.refs x = Some (Link y) -> path h y z -> path h x z this way, we would have path heap x (rep x) as an invariant and this would ensure the termination of find

24 / 32

slide-56
SLIDE 56

termination

but this is a bad idea, as each assignment in the heap requires you to re-establish all paths (some unchanged, some shortened, etc.) instead, we assign

  • a distance to each node, increasing along Link
  • a maximum distance for the whole union-find structure

25 / 32

slide-57
SLIDE 57

termination

but this is a bad idea, as each assignment in the heap requires you to re-establish all paths (some unchanged, some shortened, etc.) instead, we assign

  • a distance to each node, increasing along Link
  • a maximum distance for the whole union-find structure

maxd = 1 x 1 y z

1

v 1 u

1

25 / 32

slide-58
SLIDE 58

termination

but this is a bad idea, as each assignment in the heap requires you to re-establish all paths (some unchanged, some shortened, etc.) instead, we assign

  • a distance to each node, increasing along Link
  • a maximum distance for the whole union-find structure

maxd = 2 x 2 y z v u

2 1

25 / 32

slide-59
SLIDE 59

termination

but this is a bad idea, as each assignment in the heap requires you to re-establish all paths (some unchanged, some shortened, etc.) instead, we assign

  • a distance to each node, increasing along Link
  • a maximum distance for the whole union-find structure

maxd = 2 x 2 y z v u

2 1

25 / 32

slide-60
SLIDE 60

extraction to OCaml

Why3 extraction mechanism

  • 1. removes ghost code
  • 2. maps some Why3 symbols to OCaml symbols

here

  • type Peano.t is mapped to OCaml’s type int
  • our custom mini-heap is mapped to OCaml’s references

26 / 32

slide-61
SLIDE 61

related work

Chargu´ eraud & Pottier did a Coq proof

[ITP 2015, JAR 2017]

  • f a similar OCaml code, using CFML
  • includes a proof of complexity!
  • maps OCaml’s type int to Coq’s type Z (unsound)
  • more than 4k lines

27 / 32

slide-62
SLIDE 62

lessons learned

  • 1. modeling the heap can be easy

◮ can be local ◮ incurs a small TCB

  • 2. avoid recursive/inductive definitions for better automation

two other examples:

◮ heap stored in an array ◮ inverting a permutation in-place 28 / 32

slide-63
SLIDE 63

heap stored in an array

a 1 3 4 4 7 5 ... 1 3 4 7 4 5

1 2 3 4 5 1 3 4 2 5

29 / 32

slide-64
SLIDE 64

heap stored in an array

a 1 3 4 4 7 5 ... 1 3 4 7 4 5

1 2 3 4 5 1 3 4 2 5

it would be tempting to introduce trees but a universal, local invariant ∀i. a[i] ≤ a[2i + 1], a[2i + 2] is all you need

29 / 32

slide-65
SLIDE 65

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176] 4 3 1 5 2

30 / 32

slide-66
SLIDE 66

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176] 4 3 1 5

  • 1

30 / 32

slide-67
SLIDE 67

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176] 4 3

  • 6

1 5

  • 1

30 / 32

slide-68
SLIDE 68

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3

  • 6

1 5

  • 1

30 / 32

slide-69
SLIDE 69

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3

  • 6

1

  • 1
  • 1

30 / 32

slide-70
SLIDE 70

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3

  • 6

1

  • 1

4

30 / 32

slide-71
SLIDE 71

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3

  • 6

1 4

30 / 32

slide-72
SLIDE 72

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3

  • 6
  • 1

4

30 / 32

slide-73
SLIDE 73

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3
  • 4
  • 6
  • 1

4

30 / 32

slide-74
SLIDE 74

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3
  • 4
  • 6

1 4

30 / 32

slide-75
SLIDE 75

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3
  • 4

5 1 4

30 / 32

slide-76
SLIDE 76

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176]

  • 3

3 5 1 4

30 / 32

slide-77
SLIDE 77

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176] 2 3 5 1 4

30 / 32

slide-78
SLIDE 78

inverting a permutation in-place

Algorithm I in TAOCP [Sec. 1.3.3, page 176] 2 3 5 1 4 again it would tempting to introduce paths, orbits, cycles, etc. but again a universal, local invariant suffices

30 / 32

slide-79
SLIDE 79

many other things about Why3

  • Why3+Alt-Ergo in your browser

[http://why3.lri.fr/try/]

  • Python frontend for teaching purposes
  • Why3’s OCaml API

[BOOGIE 2011]

  • proof by reflection

[VSTTE 2016]

including imperative programs

[IJCAR 2018, next Sunday]

  • extraction to C
  • logical connectives by and so to encode proofs
  • floating-point arithmetic

[ARITH 2007]

  • checking the consistency of our library using Coq
  • preserving proofs across changes

[VSTTE 2013]

31 / 32

slide-80
SLIDE 80

visit our gallery

http://toccata.lri.fr/gallery/why3.en.html more than 150 verified programs

  • data structures: AVL/red-black trees, Fenwick trees, ropes,

skew/binomial/pairing/Braun/leftist heaps, etc.

  • algorithms: algorithm I, Tortoise and Hare, sorting, graph, etc.
  • solutions to many competitions/challenges (e.g. VerifyThis)

32 / 32