• Aucun résultat trouvé

V´erification des programmes bas´ee sur la s´emantique

Ce chapitre pr´esente les travaux commenc´es pendant mon s´ejour `a Cambridge dans l’´equipe du professeur Mike Gordon. L’objectif est de fonder la v´erification des programmes par ex´ecution symbolique sur une s´emantique op´erationnelle du langage d´efinie formellement dans l’assistant de preuves HOL4.

Je d´ecris bri`evement les principes d’HOL1 et la philosophie sp´ecifique aux

assis-tants de preuves. Je d´etaille ensuite une premi`ere approche que nous avons impl´emen-t´ee dans HOL4 et qui reprend mes travaux sur la v´erification des programmes par ex´ecution symbolique (voir section III.4 page 112), mais qui base l’ex´ecution symbol-ique sur une s´emantsymbol-ique op´erationnelle du langage d´efinie formellement dans HOL4. Ce premier travail m’a permis de me familiariser avec HOL4 et a permis une premi`ere collaboration avec Mike Gordon sur les preuves par bounded model checking, alors que le plus souvent, avec un assistant de preuves, l’usage est de r´ealiser des preuves compl`etes en g´en´erant une plus faible pr´e-condition. Ce travail est int´egr´e `a la distri-bution actuelle de HOL4 (HOL4 est t´el´echargeable sur http://hol.sourceforge. net/;nostravauxsetrouventdanslerpertoireexamples/opsemTools) et a donn´e

lieu `a un rapport de recherche [4]. J’ai choisi de le pr´esenter bien qu’il ne soit pas

encore publi´e, car il soul`eve de nombreuses questions ouvertes et perspectives dont je discute dans le chapitre VI section VI.2. Enfin, je pr´esente une r´eflexion de synth`ese qui formalise les preuves “en avant” (principe utilis´e dans le bounded model check-ing) sous la forme d’un ensemble de r`egles pour g´en´erer une plus forte post-condition et les compare aux preuves compl`etes qui produisent une plus faible pr´e-condition.

Ce travail a donn´e lieu `a une publication comme co-auteur pour c´el´ebrer le 75i`eme

anniversaire de Tony Hoare [7].

IV.1 L’assistant de preuves interactif HOL4

IV.1.1 Historique

Cette sous-section donne un bref aper¸cu de l’historique d’HOL. Mon objectif est d’en situer la philosophie de base et les majeures ´evolutions qui me paraissent significatives en tant que non sp´ecialiste mais utilisatrice pour la v´erification de programmes. L’article de Mike Gordon en l’honneur de Robin Milner [6] fournit un historique d´etaill´e.

LCF HOL est un descendant du syst`eme LCF (Logic for Computable Functions), un programme de “v´erification de preuves” cr´e´e `a l’Universit´e de Stanford par Robin Milner en 1972. La logique de LCF manipule des termes du lambda-calcul typ´e et des formules du calcul des pr´edicats. Ce syst`eme est d´ecrit de la fa¸con suivante par Robin Milner lui-mˆeme :

”The proof-checking program is designed to allow the user interactively to generate formal proofs about computable functions and functionals over a variety of domains, including those of interest to the computer

1

Dans tout ce chapˆıtre, j’emploierai le nom HOL4 pour l’impl´ementation actuelle, et j’emploierai le nom plus g´en´erique HOL pour parler de la famille des assistants de preuves en logique d’ordre sup´erieur.

IV.1. L’ASSISTANT DE PREUVES INTERACTIF HOL4 165

scientist - for example, integers, lists and computer programs and their semantics. The user’s task is alleviated by two features : a subgoaling facility and a powerful simplification mechanism”.

Une preuve avec LCF consiste donc `a travailler sur un but `a prouver en le

prouvant directement par des r`egles de simplification ou en appliquant des r`egles d’inf´erence pour g´en´erer des sous-buts.

Edimburg-LCF LCF pr´esentait deux probl`emes majeurs : la taille des preuves ´etait limit´ee par la capacit´e m´emoire, et le nombre de commandes pour manipuler les

preuves ´etait limit´e. LCF a donc donn´e lieu `a une nouvelle version “Edimburg-LCF”

qui pr´esente deux am´eliorations majeures. D’une part, seuls les r´esultats des preuves (i.e. les th´eor`emes) sont sauvegard´es. L’id´ee maˆıtresse est qu’il est inutile de garder le d´eroulement des preuves. Au contraire, les th´eor`emes sont typ´es par un type abstrait de donn´ees dont les valeurs pr´ed´efinies sont les axiomes et les op´erations sont les r`egles d’inf´erence. Ainsi, un nouveau th´eor`eme est correct par construction car il ne peut ˆetre obtenu qu’`a partir d’une d´erivation de r`egles d’inf´erence `a partir d’axiomes. D’autre part, Edimburg-LCF est bas´e sur le m´eta-langage ML pour d´efinir les r`egles d’inf´erence et les axiomes, ce qui rend le syst`eme extensible.

Cambridge-LCF Au d´ebut des ann´ees 1980, Larry Paulson et G´erard Huet ont apport´e des am´eliorations, en particulier sur ML (ces travaux ont donn´e lieu au d´eveloppement de Caml par l’´equipe de G. Huet), sur la gestion m´emoire, et la fa¸con d’impl´ementer des outils de preuve. Ces travaux ont apport´e une am´elioration cons´equente de la rapidit´e d’ex´ecution de LCF.

HOL A la mˆeme p´eriode, Mike Gordon travaillait sur la v´erification de mat´eriel`

et a appliqu´e les id´ees de composition des agents CCS “Calculus of

Communicat-ing Systems” de Robin Milner `a l’assemblage de composants mat´eriels. Pour cela,

il a d´efini la notation LSM (Logic of Sequential Machines), et l’a impl´ement´ee dans “Cambridge LCF-LSM”. Comme la mod´elisation de mat´eriel n´ecessite d’´ecrire des relations entre entr´ees/sorties du composant, les connexions internes ´etant cach´ees, et n´ecessite d’autre part de d´ecrire des signaux qui sont des fonctions sur le temps, il s’est av´er´e indispensable d’avoir une logique d’ordre sup´erieur avec quantifica-teurs. HOL (pour Higher Order Logic) est donc une impl´ementation dans LCF d’une logique d’ordre sup´erieur. Les diff´erentes ´evolutions de HOL sont pr´esent´ees en d´etail dans [6].

Applications d’HOL N’´etant pas une sp´ecialiste de HOL, je ne donne pas ici un

´etat de l’art exhaustif mais me contente de donner un aper¸cu des travaux que j’ai

´etudi´es lors de mon s´ejour `a Cambridge.

Le d´emonstrateur HOL et ses d´eriv´es ont ´et´e appliqu´es `a de nombreux

do-maines allant de la v´erification r´ealis´ee compl`etement “`a la main” de th´eor`emes

math´ematiques (e.g. la preuve de la consistance de l’axiome du choix que Lawrence

automatis´ees comme la v´erification de l’impl´ementation d’un Lisp sur diff´erentes architectures [9].

HOL a ´et´e utilis´e `a son origine pour la v´erification de mat´eriel, avec les travaux

pr´ecurseurs de Mike Gordon et Warren Hunt pr´esent´es section II.1.3 page 28. Ces travaux ont ´et´e poursuivis notamment pour formaliser en HOL le jeu d’instructions du processeur ARM6 ainsi que sa micro-architecture et v´erifier la correction entre ces deux niveaux [5]. Les travaux plus r´ecents de l’´equipe de Mike Gordon portent sur la compilation de langages assembleur (voir section II.3 page 37).

Enfin, les travaux actuels concernent aussi des aspects plus th´eoriques, pour enrichir le cœur mˆeme d’HOL. Il s’agit en particulier de la formalisation en HOL de la “separation logic”, une logique qui permet de g´erer s´epar´ement deux ´etats. Cela est utilis´e en particulier pour mod´eliser la programmation objet en tenant compte du contexte d’appel des m´ethodes [13, 10]. D’autre part, de nombreux efforts portent sur l’int´egration d’outils externes comme un solveur SAT [1, 14] ou un solveur SMT (travail en cours de Tjark Weber). Le principe est d’appeler le solveur externe pour son efficacit´e et d’utiliser des informations de la preuve effectu´ee pour reconstruire une preuve en HOL. Par exemple, pour un solveur SAT, si la formule est satisfiable,

alors le solveur fournit un exemple qui sert `a g´en´erer un th´eor`eme HOL grˆace `a la

tactique “EXISTS TAC” (voir exemple IV.2) ; si la formule n’est pas satisfiable on peut utiliser la d´erivation des r´esolutions qui ont permis de g´en´erer la clause vide [14].

IV.1.2 Caract´eristiques principales de HOL4

Je pr´esente ici de fa¸con succincte les id´ees de base pour le d´eveloppement d’une preuve avec HOL4. Ceci est illustr´e avec l’exemple fourni dans le tutorial de la distribution HOL qui d´efinit et montre des propri´et´es de la division euclidienne.

HOL encourage les d´efinitions plutˆot que les postulats d’axiomes comme dans

LCF. En effet, la logique d’ordre sup´erieur rend possible la sp´ecification de nom-breux objets math´ematiques uniquement `a partir de d´efinitions. Une session avec HOL4 se pr´esente donc de la fa¸con suivante. Tout d’abord il faut d´efinir (ou utiliser) une th´eorie qui contient un ensemble de types, de signatures, d’axiomes et de th´eor`emes. Les types sont pr´ed´efinis ou d´efinis par l’utilisateur (de type Hol type). Les termes sont des variables, des constantes, des applications de fonctions et des lambda-abstractions. Les th´eor`emes sont des termes particuliers de type thm, not´es

hypothese ⊢ conclusion (un axiome ´etant un th´eor`eme particulier o`u l’hypoth`ese

est vide). L’exemple IV.1 pr´esente une th´eorie d´efinie pour prouver le th´eor`eme d’Euclide.

Exemple IV.1 (Th´eorie de la division euclidienne) La th´eorie de la division

euclidienne utilise la th´eorie de l’arithm´etique qui contient les types, d´efinitions et propri´et´es ´el´ementaires de l’arithm´etique (e.g. le type num, la constante 0, les

op´erations ´el´ementaires +, −, ... d´efinies `a partir de l’op´erateur suc et 0, la propri´et´e

de commutativit´e du +, ...). Elle ajoute `a cette th´eorie la d´efinition de la divisibilit´e

IV.1. L’ASSISTANT DE PREUVES INTERACTIF HOL4 167

syntaxe usuelle syntaxe HOL

∧ /\ ∨ \/ ¬ ˜ ∀ ! ∃ ? ⇒ ==> ⊢ |– λx. \x.

Fig. IV.1 – Syntaxe des principaux op´erateurs logiques en HOL

th´eor`emes sont prouv´es et ajout´es `a la th´eorie. Les lignes suivantes sont directement

extraites du fichier d’exemple “euclid.sml” de la distribution de HOL ((*1*) est un commentaire). La syntaxe des principaux op´erateurs HOL est donn´ee figure IV.1. (*1*) open arithmeticTheory (*2*) val divides_def = Define ‘divides a b = ?x. b = a * x‘; (*3*) val prime_def = Define ‘prime p = ~(p=1) /\ !x. x divides p ==> (x=1) \/ (x=p)‘; (*4*) val DIVIDES_0 = store_thm

("DIVIDES_0",

‘‘!x. x divides 0‘‘,

METIS_TAC [divides_def,MULT_CLAUSES]);

La ligne (*1*) indique que la th´eorie d’Euclide utilise toutes les d´efinitions et th´eo-r`emes de la th´eorie de l’arithm´etique. La ligne (*2*) d´efinit la division euclidienne sous le nom de “divides” avec la d´efinition : a divise b si et seulement si il existe x tel

que b = a∗x. La ligne (*3*) d´efinit la primalit´e d’un nombre p sous le nom de “prime”

avec la d´efinition que p est premier si et seulement si p est diff´erent de 1 et pour tout x, si x divise p alors x = 1 ou x = p. La ligne (*4*) demande d’ajouter `a la th´eorie le th´eor`eme de nom “DIVIDES 0” qui indique que pour tout x, x divise 0. Plus pr´ecis´ement, ce th´eor`eme est d’abord prouv´e en appliquant la tactique “METIS” (qui combine plusieurs tactiques ´el´ementaires et permet de prouver efficacement des propri´et´es de l’arithm´etique), et en utilisant de fa¸con sp´ecifique la d´efinition de “divides” et le th´eor`eme “MULT CLAUSES” de la th´eorie de l’arithm´etique :

|- !m n. (0 * m = 0) /\ (m * 0 = 0) /\ (1 * m = m) /\ (m * 1 = m)

/\ (SUC m * n = m * n + n) /\ (m * SUC n = m + m * n)

HOL est un assistant de preuves interactif c’est-`a-dire qu’il aide

l’utilisa-teur `a effectuer la preuve en offrant des tactiques pr´ed´efinies, en v´erifiant que

Nom Syntaxe Th´eor`eme renvoy´e

Assumption ASSUME t t|- t

Reflexivity REFL t |- t=t

Beta-conversion BETA CONV (\x.t1)t2 |-(\x.t1)t2 = t1[t2/x]

Substitution SUBST T1|-t1=t1’,...,Tn|-tn=tn’, T1...TN T|-t(t1’,...,tn’) T|-t(t1,...,tn)

Abstraction ABS x T|-t1=t2 T|-(\x.t1) = (\x.t2)

Discharge DISCH t1 T|-t2 T-{t1}|-t1 ==> t2

Modus Ponens MP T1|-t1 ==> t2, T2|-t1 T1 T2|-t2

Fig. IV.2 – R`egles d’inf´erence primitives

r´esultat. Il offre sept r`egles d’inf´erence primitives qui sont pr´esent´ees dans la figure IV.2. Par exemple, la r`egle d’inf´erence “ASSUME” introduit le th´eor`eme t comme une hypoth`ese qui valide la conclusion t. L’utilisateur peut d´efinir lui-mˆeme sa propre tactique comme un assemblage de tactiques primitives ou de tactiques pr´e-d´efinies et en indiquant quels th´eor`emes utiliser.

Le d´eroulement d’une preuve en HOL est de deux types : les preuves en avant

qui utilisent principalement les r`egles d’inf´erence “ASSUME”, “MP” et “DISCH” (de telles preuves sont en g´en´eral assez d´elicates `a mener car peu intuitives), et les preuves dirig´ees par des buts. Dans ce dernier cas, les preuves sont des successions

d’utilisation de r`egles d’inf´erence primitives ou pr´e-d´efinies. `A chaque instant,

l’util-isateur indique quelle tactique il veut utiliser. HOL4 v´erifie que la tactique s’applique

et calcule les sous-buts `a prouver pour finir la preuve. Le processus est rendu plus

efficace grˆace `a un ensemble de proc´edures de d´ecision associ´ees `a certaines th´eories

(e.g. v´erification de tautologies bas´ee sur la repr´esentation des BDDs). De plus, la recherche de la preuve peut ˆetre dissoci´ee de la preuve elle-mˆeme. Des programmes externes (comme un solveur SAT par exemple) peuvent ˆetre utilis´es comme des or-acles pour fournir le r´esultat d’une preuve, sans que cette preuve ait besoin d’ˆetre construite en HOL (dans ce cas, le th´eor`eme r´esultat est “´etiquet´e” comme oracle pour que l’on sache qu’il n’a pas ´et´e prouv´e avec la logique d’HOL). L’exemple IV.2 montre la preuve d’un lemme pour th´eor`eme d’Euclide.

Exemple IV.2 (Preuve d’un lemme pour le th´eor`eme d’Euclide) La

preu-ve du th´eor`eme d’Euclide est assez longue et complexe et peut ˆetre trouv´ee dans la distribution HOL et dans l’annexe VII.2.1 page 271. Le th´eor`eme d’Euclide qui dit

que l’ensemble des nombres premiers est infini (i.e. !n. ?p. n < p ∧ prime p) est

prouv´e par induction sur n, il est donc n´ecessaire de prouver le lemme interm´ediaire :

!x. divides x 0pour le cas de base. Ce lemme peut ˆetre prouv´e directement grˆace

`

a la tactique “METIS TAC” comme dans l’exemple IV.1. Nous montrons ici ce qui se passe si l’on utilise uniquement des tactiques primitives. Pour ˆetre plus pr´ecise et montrer la pile des buts, je donne une copie textuelle de l’interaction avec HOL4.

Tout d’abord, on donne le but `a prouver avec la commande “g”.

IV.1. L’ASSISTANT DE PREUVES INTERACTIF HOL4 169

> val it =

Proof manager status: 1 proof. 1. Incomplete:

Initial goal: !x. divides x 0 : proofs

Il y a une preuve en cours et un but `a prouver. On demande maintenant `a “expanser”

(commande e) la tactique de r´e´ecriture “RW TAC” en utilisant l’ensemble de r`egles de simplification de l’arithm´etique “arith ss” et en utilisant la d´efinition de la division “[divides def]”.

- e (RW TAC arith ss [divides def ]); OK..

1 subgoal:

> val it = ?x’. (x = 0) ∨ (x’ = 0)

Lors de l’expansion de la tactique, la d´efinition de “divides” a ´et´e appliqu´ee avec a =

x et b = 0 pour obtenir divides x 0 = ?x’.0=x*x’ et le th´eor`emeMULT EQ 0 = |- !m

n.(m*n=0) = (m=0) ∨ (n=0) a ´et´e utilis´e comme r`egle de r´e´ecriture. Il reste alors `a

prouver le sous-but?x’. (x = 0) ∨ (x’ = 0). Ce but est prouv´e de fa¸con triviale si

l’on instancie x avec 0 ; il suffit pour cela d’utiliser la tactique “EXISTS TAC”.

- e (EXISTS TAC ‘‘0‘‘); OK.. 1 subgoal: > val it = (x = 0) ∨ (0 = 0) - e (RW TAC arith ss []); OK.. Goal proved. |- (x = 0) ∨ (0 = 0) Goal proved. |- ?x’. (x = 0) ∨ (x’ = 0)

> val it = Initial goal proved. |- !x. divides x 0

Ceci termine la preuve du lemme. ´Evidemment, mˆeme si des tactiques comme

la tactique “METIS TAC” permettent de prouver un grand nombre de formules de l’arithm´etique sans autre pr´ecision, mener une preuve avec HOL4 requiert une grande habitude et une bonne connaissance des tactiques et th´eor`emes existants.♯

R`egle de simplification pour la v´erification de programmes Je termine

cette sous-section introductive `a HOL4 par deux exemples de r`egles que nous avons

d´efinies dans le cadre de la v´erification des programmes Java par rapport `a une

sp´ecification JML. L’exemple IV.3 illustre une tactique d´efinie pour calculer la n´egation de la sp´ecification JML et l’exemple IV.4 illustre comment transformer une quantification universelle sur un domaine fini en une conjonction. Ce dernier exemple illustre aussi le fait qu’HOL4 a une logique d’ordre sup´erieur : la tactique

Exemple IV.3 (N´egation d’une sp´ecification JML) Bon nombre des sp´ecifica-tions JML des programmes que nous avons v´erifi´es sont en fait une conjonction des cas d’utilisation de la m´ethode. Par exemple, pour le programme T ritype de clas-sification d’un triangle en fonction de trois entr´ees i, j et k (voir figure III.14 page 123), la sp´ecification JML est :

/*@ requires (i>=0)&&(j>=0)&&(k>=0); @ ensures

@ ((i+j<=k)||(j+k<=i)||(i+k<=j)) ==> \result == 4 &&

@ !((i+j<=k)||(j+k<=i)||(i+k<=j))&&((i==j)&&(j==k)) ==> \result == 3 && @ !((i+j<=k)||(j+k<=i)||(i+k<=j))&&!((i==j)&&(j==k))

@ &&((i==j)||(j==k)||(i==k)) ==> \result == 2 && @ !((i+j<=k)||(j+k<=i)||(i+k<=j))&&!((i==j)&&(j==k)) @ &&!((i==j)||(j==k)||(i==k)) ==> \result == 1; @*/

Pour utiliser la programmation par contraintes comme une proc´edure de d´ecision, nous prenons la n´egation de la sp´ecification. Pour calculer efficacement cette n´egation, tout en gardant une forme qui reste proche de la sp´ecification initiale (et on peut l’esp´erer des expressions du programme), nous avons d´efini une r`egle de

conver-sion2 qui utilise la loi de De Morgan `a un seul niveau. La r`egle de conversion est la

suivante :

NOT CONJ IMP CONV ¬((A1 ==> B1) ∧ ... ∧ (An ==> Bn) ∧ TM) = |- (A1 ∧ ¬B1) ∨ ... ∨ (An ∧ ¬Bn) ∨ ¬TM

Elle a ´et´e ´ecrite en ML, et utilise des r`egles de conversion et des th´eor`emes basiques comme par exemple le th´eor`eme de la th´eorie des bool´eens qui ´enonce la loi de De Morgan :

DE MORGAN AND THM = !A B. ¬(A ∧ B) = ¬A ∨ ¬B

Dans cette r`egle de conversion les Ai et Bi sont des termes quelconques.♯

Exemple IV.4 (Quantificateur universel born´e) La primitive \forall de JML

permet d’exprimer une propri´et´e pour un ensemble de valeurs comprises entre deux bornes. Par exemple, la pr´e-condition de la recherche binaire d’une valeur dans un tableau en JML est la suivante :

\forall int i ;0<=i && i<a.length-1 ; a[i]<=a[i+1]

La r`egle de conversionboundedForAll CONV, ´ecrite en ML, utilise des r`egles de

con-version basiques et le th´eor`eme d’ordre sup´erieur suivant :

BOUNDED FORALL THM = |- !c. 0<c ==> (( !n. n<c ==> P n) = P (c-1) !n. n<c-1 ==> P n) : thm

Ce th´eor`eme expanse d’un cran la propri´et´e P (n) vraie pour tout n inf´erieur `a c. P est ici un pr´edicat quelconque qui s’applique `a la variable n ; c’est en ce sens que la r`egle de conversion est d’ordre sup´erieur.

Cette r`egle de conversion simplifie au passage les sous-termes obtenus. Appliqu´ee `

a une fonction f quelconque, elle calcule simplement la conjonction de tous les f (i) pour i < c.

2Une r`egle de conversion est un th´eor`eme qui est utilis´e par une tactique de r´e´ecriture de gauche `

IV.2. EX ´ECUTION SYMBOLIQUE BAS ´EE SUR LA S ´EMANTIQUE 171

-val tm = ‘‘ !n. n<8 ==> f(n)‘‘ ; -val btm = boundedForAll CONV tm ; > val btm = |- ( !n. n<8 ==> f n) =

f 7 ∧ f 6 ∧ f 5 ∧ f 4 ∧ f 3 ∧ f 2 ∧ f 1 ∧ f 0 : thm

Si maintenant f est le pr´edicat n < n + 1 qui est toujours vrai, la r`egle de

conversion renvoie T c’est-`a-dire la valeur “vraie”.

-val tm2 = ‘‘ !n. n < 8 ==> n<n+1‘‘ ; -val btm2 = boundedForAll CONV tm2

> val btm2 = |- ( !n. n<8 ==> n<n+1) = T : thm

IV.2 V´erification des programmes par ex´ecution

sym-bolique bas´ee sur la s´emantique

Je pr´esente ici mes travaux sur le bounded model checking (BMC) de programmes dont la s´emantique est d´efinie en logique d’ordre sup´erieur. L’id´ee initiale est de trouver un compromis entre l’efficacit´e fournie par des solveurs externes et une plus grande correction en basant les ´etapes de l’ex´ecution symbolique sur la s´emantique

d´efinie dans HOL4. Notre objectif `a long terme est d’offrir aussi bien une preuve

incompl`ete par BMC qu’une preuve compl`ete avec HOL4 dans un cadre s´emantique coh´erent.

IV.2.1 Principes

Le principe g´en´eral est celui pr´esent´e dans l’algorithme section III.4 figure III.13 : le programme est ex´ecut´e symboliquement en coupant `a la vol´ee les chemins