340 likes | 559 Views
in collaboration with University of Kent Clara Benac Earle SICS Mads Dam Lars-Åke Fredlund Dilian Gurov Gena Chugunov CWI Izak van Langevelde Wan Fokkink Jaco van de Pol Stefan Blom
E N D
in collaboration with University of Kent Clara Benac Earle SICS Mads Dam Lars-Åke Fredlund Dilian Gurov Gena Chugunov CWI Izak van Langevelde Wan Fokkink Jaco van de Pol Stefan Blom Inria Rhône-alpes Hubert Garavel Radu Mateescu RWTH Aachen Thomas Noll Martin Leucker Jürgen Giesl LFCIA Juanjo Sánchez Penas in collaboration with University of Kent SICS CWI Inria Rhône-alpes RWTH Aachen LFCIA Formal verification of software Thomas Arts Ericsson Stockholm, Sweden
Why formal verification ? • cut down on testing/maintenance cost • Common Criteria (ISO 15408) prescribes it • allow more complex products to be built For what purpose ? • find bugs in design/software • prove correctness
Where to apply ? • Verify design • Verify software • Verify software implements design • Verify design equivalence • Verify program equivalence case-studies WAP Database lookup Resource locking leader election TCAP
Formal Verification of Design Make a formal design (specification language) Formalize properties Find a technique to verify that the formal property holds for the formal design
C D A B locker client client client Formal Verification of Design (example) Design of resource locker
locker client idle request A, B ok request resources release ok critical release idle Formal Verification of Design (example) idle release request resources available ? pending available? add pending idle ok idle ok rm pending idle
idle request resources ok critical release idle Client specification client_idle = send(request_recources). receive(ok). client_critical client_critical = send(release). client_idle init locker_idle || client_idle
idle release request resources available ? pending available? add pending idle ok idle ok rm pending idle locker_idle = receive(request_resources). (available. send(ok). locker_idle + not_available. add_pending. locker_idle ) + receive(release). locker_intermediate locker_intermediate = pending_available. send(ok). rm_pending. locker_intermediate + not_pending_available. locker_idle Locker specification
State space generation • Clearly there are deadlock • states in the state space • They correspond to the situation where: • resource not available • resource available but no client waiting for it • Both situations cannot occur in reality
2 clients and a locker Non-determinism gives possibility that both clients are waiting for the resource Note that both clients can get access to the same resource
Formal Verification of Design have to make formal design not enough detail for interesting properties no feeling for implementation (memory consumption, speed) implementation may divert from design
Formal Verification of Design More and more details are added to the design in order to check interesting properties. CLAIM: For Interesting properties one need to add details until the specification is executable, i.e. is a program.
Formal verification of a Program IDEA: Use code as formal design document + Libraries can be used as-is + Programming languages support debug facilities, testing possibilities, etc. + Designers do not need to learn a new language
idle request resources ok critical release idle Formal verification of a Program (example) -module(client). start(Locker) -> spawn(fun() -> loop(Locker) end). loop(Locker) -> Tag = ref(), Locker!{request,[a],self(),Tag}, receive {ok,Tag} -> critical(), Locker!{release,self()}, loop() end.
idle release request resources available ? pending available? add pending idle idle ok ok rm pending idle Formal verification of a Program (example) -module(locker). loop(Locks) -> receive {request,Rs,Client,Tag} -> case available(Locks,Rs) of true -> Client ! {ok,Tag}, loop(update(Locks)); false -> loop(add(Locks,Rs, {Client,Tag})) end; {release,Client} -> ...
Formal verification of a Program IDEA: Use code as formal design document + Libraries can be used as-is + Programming languages support debug facilities, testing possibilities, etc. + Designers do not need to learn a new language design patterns theorem prover or abstraction - Too much detail no feeling for design - Risk of infinite state space
Formal verification of a Program (example) use the generic server design pattern to implement the locker init(Resources) -> {ok, built_locks(Resources)}. handle_call({request,Rs},Client,Locks) -> case available(Rs,Locks) of true -> {reply,ok,update(Locks)}; false -> {noreply,add(Locks,Rs,Client)} end; ....
Formal verification of a Program Techniques: Theorem Proving expressive logic allows (co-)induction large manual effort Model Checking limited logic (e.g. CTL) little manual effort Ad Hoc solutions
State Space Generation We developed a tool to generate all possible traces for simple client-server applications Erlang modules our Tool
State Space Generation In Erlang we use a supervisor design pattern to handle fault-tolerance. If a process dies, it’s supervisor restarts it. supervisor locker gen_server supervisor client client client client client
State Space Generation We use supervisor design pattern to obtain initialization information for transition diagram We build one state space per configuration start the locker with 2 clients supervisor:start(locker_sup,init,[[[a,b],[b,c]]]). start verification with 2 clients etomcrl:start(locker_sup,init,[[[a,b],[b,c]]]). supervisor locker gen_server supervisor client client
locker.erl our Tool client.erl init.erl our Tool our Tool our Tool our Tool EtoE rest tool State Space Generation locker.erl client.erl locker_sup.erl client_sup.erl instantiation
locker.erl client.erl locker.erl client.erl init.erl locker_sup.erl client_sup.erl instantiation EtoE rest tool rest tool rest tool rest tool rest tool State Space Generation tomcrl.erl instantiation EtoPmcrl
locker.erl client.erl locker.erl client.erl init.erl locker_sup.erl client_sup.erl instantiation locker.mCRL EtoE rest tool toMCRL rest tool rest tool rest tool CWI tool instantiator State Space Generation tomcrl.erl instantiation rest tool EtoPmcrl
locker.erl client.erl locker.erl client.erl init.erl locker_sup.erl client_sup.erl instantiation locker.aut EtoE rest tool CADP State Space Generation tomcrl.erl instantiation locker.mCRL toMCRL rest tool CWI tool instantiator EtoPmcrl
macro UNTIL (Act1,Act2) = [true*.(Act1).(not(Act2))*.(Act1)]false end_macro UNTIL('action_use(.*a.*)','action_free(.*a.*)') and UNTIL('action_use(.*b.*)','action_free(.*b.*)') and UNTIL('action_use(.*c.*)','action_free(.*c.*)') Model Checking Software
reply(2,ok) reply(1,ok) request(2,[B]) request(1,[A]) Model Checking Software Non Starvation: [-*. request(1,[A])] mu X.(<->true /\ [not reply(1,ok)]X) /\ [-*. request(2,[A])] mu X.(<->true /\ [not reply(2,ok)]X) /\ ... [-*. request(1,[B])] mu X.(<->true /\ [not reply(1,ok)]X) /\ ....
tau reply(1,ok) tau request(1,[A]) Model Checking Software Non Starvation: [-*. request(1,[A])] mu X.(<->true /\ [not reply(1,ok)]X) /\ [-*. request(2,[A])] mu X.(<->true /\ [not reply(2,ok)]X) /\ ... Safety reduction (trace equivalence) Non-starvation per group of resources. Hide all actions of which resources are not in closure of resources you are intersted in
Model Checking Software Abstraction may be needed to keep state space finite: Generic abstraction mechanism by providing abstraction functions over messages and server state This allows to obtain a design from a program! not yet implemented in combination with CWI tool
Results Automatic state space generation from rich class of Erlang programs Several case studies evaluated: model checking for software is possible more work to do: more design patterns property patterns in Erlang style add generic abstraction mechanism without design patterns or comments largest case-study is about 300 lines of code
Future • how many configurations do we need to check? • fault tolerance: • - restarting processes • compositionality: • - N lockers exchanging information • - lockers on top of leader election