• Aucun résultat trouvé

Fonction delete_substr spécifiée et prouvée automatiquement

7

DÉCOUVERTE DE FAIBLESSES DE

SOUS-CONTRATS

N

ous avons vu au chapitre précédent que la méthode de détection de non-conformités par génération de tests peut n’en trouver aucune alors que la preuve échoue. Dans ce cas il est possible que la preuve échoue soit parce que le prouveur n’est pas assez puissant pour mener la preuve à terme, soit parce qu’il ne dispose pas de suffisamment d’hypothèses à partir des sous-contrats (contrats de boucles et contrats des fonctions appelées). En effet, il se peut par exemple qu’un invariant de boucle soit prouvé mais qu’il soit insuffisant pour prouver la postcondition de la fonction sous test. Dans ce cas, nous disons qu’il y a une faiblesse du sous-contrat. Nous utilisons la génération de tests pour exhiber ces faiblesses.

Dans ce chapitre, nous présentons la notion de faiblesse de l’ensemble des sous-contrats et de faiblesse d’un sous-contrat, pour les sous-contrats de la fonction sous vérification que sont les contrats de boucles et les contrats de fonctions appelées. Nous présen- tons également les spécificités de la traduction des annotations pour la détection des fai- blesses de sous-contrats par rapport à la traduction pour la détection de non-conformités présentée au chapitre 4.

La partie 7.1 présente la notion de faiblesse de l’ensemble des sous-contrats et la par- tie 7.2 présente la notion de faiblesse d’un sous-contrat. La partie 7.3 continue le cas pratique du chapitre 6 pour montrer l’intérêt de la détection des faiblesses des sous- contrats.

7.1 D

ÉTECTION DE FAIBLESSE DE L

ENSEMBLE DES SOUS

-

CONTRATS

Avant de présenter nos définitions de faiblesses de sous-contrat, nous avons besoin de définir des concepts supplémentaires. Une boucle (respectivement une fonction, une as- sertion) non-imbriquéede f est une boucle (respectivement une fonction appelée, une assertion) de f en dehors de toute boucle de f . Unsous-contrat de f est le contrat d’une boucle ou d’une fonction non-imbriquée de f . Uneannotation non-imbriquéede f est soit une assertion non-imbriquée soit une annotation d’un sous-contrat de f . Par exemple, la fonctiondelete_substrde la figure 6.3 du chapitre 6 a quatre sous-contrats : le contrat de

la fonction appelée find_substret le contrat de chacune des trois boucles de la fonction

delete_substr. Les contrats éventuels des boucles defind_substrsont des sous-contrats

1 /*@ assigns k1,...,kN; 2 @ ensures P; */ 3 T ypeg g(...){ code1; } 4 5 6 7 8 T ypef f(...){ code2; 9 g(Argsg); 10 code3; } → 1 T ypeg g_swd(...){ 2 k1=Nondet(); ... kN=Nondet();

3 T ypeg ret = Nondet();

4 int post; Spec2Code(P, post);

5 fassume(post); return ret;

6 } //respects contract of g

7 T ypeg g(...){ code1; } 8 T ypef f(...){ code2; 9 g_swd(Argsg);

10 code3; }

FIGURE7.1 – (a) Un contrat c ∈ C d’une fonction g appelée par f , et (b) sa traduction pour

la détection des faiblesses de sous-contrats de fonction appelée

1 T ypef f(...){ code1; 2 /*@ loop assigns x1,...,xN; 3 @ loop invariant I; */ 4 while(b){ code2; } 5 code3; } → 1 T ypef f(...){ code1; 2 x1=Nondet(); ... xN=Nondet();

3 int inv1; Spec2Code(I, inv1);

4 fassume(inv1 && !b); //respects loop contract

5 code3; }

FIGURE7.2 – (a) Un contrat c ∈ C d’une boucle de f , et (b) sa traduction pour la détection

des faiblesses de sous-contrats de boucle

defind_substrmais pas des sous-contrats dedelete_substr.

Nous nous concentrons sur les annotations non-imbriquées de f et supposons que tous les sous-contrats de f sont respectés : les fonctions appelées par f respectent leur contrat et les boucles de f préservent leurs invariants et respectent les annotations im- briquées. Soit cf le contrat de f , C l’ensemble des sous-contrats non-imbriqués de f , et

Al’ensemble des annotations non-imbriquées de f et des annotations de cf. En d’autres

termes, A contient les annotations des contrats dans C ∪ {cf}, ainsi que les assertions

non-imbriquées de f . Nous supposons également que chaque sous-contrat de f contient une clauseassigns ouloop assigns. Cette hypothèse n’est pas limitative puisqu’une telle

clause est de toute manière nécessaire à la preuve de toute fonction ou boucle non tri- viale.

Afin d’appliquer la génération de tests aux contrats des fonctions appelées et des boucles de C au lieu de leur code, nous utilisons une transformation de programme qui produit un nouveau programme PGSW(pour global subcontract weakness) à partir de P. Le code de

chaque appel de fonction et de chaque boucle de f est remplacé par un nouveau code dérivé de leur contrat de la manière suivante.

Pour un contrat c ∈ C d’une fonction g appelée par f, la transformation de programme

(illustrée par la figure 7.1) génère une nouvelle fonction g_swd ayant la même signature

et dont le code simule tous les comportements possibles respectant la postcondition du contrat c. Chaque appel àgdansfest remplacé par un appel àg_swd. Tout d’abord,g_swd

permet aux variables (et plus généralement aux left-values) présentes dans la clause

assigns de c de changer de valeur (ligne 2 de la figure 7.1(b)). Ceci est possible en

affectant une valeur non-déterministe du type adéquat, dont la génération est ici no- tée par Nondet()(ou simplement en utilisant un tableau contenant les variables d’entrée

fraîches, dans lequel on va lire de nouvelles valeurs pour chaque appel de la fonctiong).

La règle α-ASSUME-ASSIGNSde la figure 7.3 formalise la traduction de la clauseassigns

où X = {x1, ..., xm}. Si le type de retour de g n’est pasvoid, une valeur non-déterministe

supplémentaire est générée pour la valeur de retourret(ligne 3 de la figure 7.1(b)). Enfin,

α-ASSUME-ASSIGNS (Endf, x1) τ 7→(I1, e1) ... (Endf, xm) τ 7→(Im, em) (Endf,assignsX;) α

7→ I1·(Endf, e1= Nondet();) · ... · Im·(Endf, em= Nondet();)

α-ASSUME-POST (Endf, p) π 7→(I, e) (Endf,ensuresp;) α 7→ I ·(Endf, fassume(e);)