• Aucun résultat trouvé

Méthodes d’analyse semi-automatiques

Nous citons dans cette section diverses méthodes semi-automatique pour l’analyse de pro-grammes manipulant des structures de données. L’interprétation abstraite ne nécessite qu’une faible intervention de l’utilisateur. Celui-ci n’aura qu’à choisir les domaines abstraits adéquats à l’analyse de tout un programme. À l’inverse, pour les méthodes d’analyse semi-automatiques, une intervention importante de l’utilisateur est requise et il devra, selon les cas, fournir des inva-riants ou préciser des paramètres d’analyses pour l’analyse d’une fonction ou d’un morceau de programme.

Si les approches peuvent s’éloigner de l’interprétation abstraite, on retrouvera tout de même des problématiques similaires dans l’analyse de programmes manipulant des structures de don-nées.

9.3.1 Logiques décidables sur les tableaux et les structures de données

Dans le domaine de la vérification, de nombreux travaux portent sur la définition de logiques décidables dans lesquelles s’expriment des propriétés de programmes et sur le développement de procédures de décision dans ces logiques. A partir d’un programme annoté avec des pré-conditions, des post-conditions et des invariants de boucle appartenant à une logique décidable, on utilise ces procédures de décision afin de prouver que les secondes sont bien impliquées par les premières. La plupart de ces méthodes nécessitent que l’utilisateur donne également les invariants de boucles.

Nous décrivons dans cette section quelques travaux récents sur des logiques destinées à la vérification de programmes manipulant des tableaux ou des structures de données. Les logiques que nous évoquerons permettent toutes la quantification universelle sur les cellules.

La logique décidable introduite dans [BMS06] est le fragment APF2qui autorise des formules de la forme

∀L, ϕ(L)⇒ψ(L)

où L est un ensemble de variables entières quantifiées universellement et ϕ et ψ sont deux formules, elles aussi contraintes :

• les atomes deϕsont ou bien l’égalité=ou bien l’inégalité≤;

• les expressions comparées dansϕsont ou bien une variable` ∈ Lou bien une expression dans l’arithmétique de Presburger [Pre29] sur les variables du programme ;

• ψest une formule d’un fragment décidable dans lequel on s’autorise à ajouter des expres-sionA[`] pour un tableauAet une variable`∈`donnés.

Ce fragment contient par exemple la formule ∀`1, `2, (i≤`1 ≤`2 ≤ j)⇒(A[`1]≤A[`2]) exprimant qu’un tableauAest trié entre les indicesiet j.

Les auteurs identifient également quelques extensions de cette logique qui deviennent indéci-dables. Le résultat de décidabilité est brisé

• quand on introduit des accès imbriqués aux tableauxA[B[`]] avec`∈ L; • quand on introduit dansϕdes accèsA[`] avec`∈ L;

• quand on s’autorise à utiliser l’arithmétique de Presssburger sur les variables`∈ L. 2. Acronyme de « Array Property Fragment »

Les auteurs de [HIV08] introduisent la logique LIA3 incomparable avec AFP. La forme gé-nérale des formules est toujours

∀L, ϕ(L)⇒ψ(L)

mais les contraintes surϕetψdifférent :

• ϕpeut contenir des contraintes de la forme`=`0+cavec`∈ Letc∈Z, mais contrairement à AFP, ne permet pas d’exprimer d’inégalités entre les variables deL;

• ϕpeut contenir des contraintes de congruence`≡n cavecc,n∈N,c<n;

• ϕpeut contenir des comparaisons entre les variables deLet des sommes ou différences des variables d’indice du programme et de constantes ;

• ψest une contrainte de zones pouvant faire intervenir des termesA[`].

Notons que puisqu’il est possible d’avoir des contraintes` =`0+con peut aussi bien autoriser

A[`] queA[`0+c] dansψ.

La logique DWL4présentée dans [BHJS07] permet de raisonner sur des mots. Les mots pour-raient être par exemple des suites de valeurs d’une liste chaînée ou d’un tableau. Les formules de cette logique autorisent la comparaison large et stricte des variables d’indice utilisées dans les accès aux mots ainsi que leur comparaison à zero. Elle autorise également n’importe quel atome ou relation d’une théorie décidable sur les contenus, en étendant cette théorie avec des accès aux tableaux par une variable d’indice. Les auteurs en distinguent un fragment décidable, celui des formules de la forme∃ψoùψest une formule sans quantificateur.

La logique DWL présente le défaut de ne pas être close par les manipulations de pointeur. La logique CSL5 [BDES09] n’a pas ce défaut. Cette dernière logique permet de travailler sur des programmes manipulant des structures dynamiquement liées, des tableaux et des combinaisons des deux. Elle permet d’exprimer

• des contraintes sur l’accessibilité entre deux positions du tas en suivant des champs poin-teurs,

• des contraintes linéaires sur la taille des listes et les indices des tableaux et • des contraintes sur les valeurs des données.

La logique UABE6 introduite dans [ZHWG10] considère le cas où l’ensemble des valeurs possibles pour les cellules de tableau est borné. Ceci est motivé par le fait que dans la pratique, les entiers sont classiquement codés sur un nombre borné de bits. Sous cette condition la logique est décidable et autorise une large classe de formules permettant l’alternance de quantificateurs et les accès imbriqués aux cellules.

Pour appliquer les procédures des décision et vérifier que les post-condtions sont impliquées par les pré-conditions, il est en général nécessaire que l’utilisateur donne également les inva-riants de boucles. Néanmoins, [BHI+09] propose une méthode pour automatiser la génération d’invariants dans le cas de programme avec des boucles non-imbriquées. Leur méthode permet, dans le cas de la logique LIA [HIV08] d’inférer les post-conditions des boucles réduisant ainsi le besoin d’intervention humaine pour ces programmes.

3. Acronyme de « Logic on Integer Arrays » 4. Acronyme de « Data Word Logic »

5. Acronyme de « Composite Structures Logic »

Conclusion Le principe est relativement éloigné de celui de l’interprétation abstraite. L’inter-prétation abstraite permet de synthétiser les invariants et de découvrir des propriétés, sans aide humaine et sur n’importe quelle classe de programme pourvu qu’on ait fourni la sémantique abstraite adéquate. Les méthodes d’analyse par interprétation abstraite sont généralement moins coûteuses que les procédures de décision. Elles n’ont pas besoin de travailler sur un fragment de logique décidable et peuvent donc s’aventurer sur des classes plus vastes de formules. En contrepartie, l’interprétation abstraite ne fournit aucune garantie de résultat : si elle échoue à dé-couvrir une propriété, cela ne signifie pas que la propriété est fausse et on ne peut rien conclure. Notons également que l’interprétation abstraite est souvent plus facile à étendre, par la définition de nouveaux domaines abstraits et leur combinaison.

9.3.2 Abstraction par prédicats

L’abstraction par prédicats [GS97] est une technique d’interprétation abstraite permettant de désigner les ensembles d’états atteignables par les prédicats qu’ils vérifient. On choisit un en-semble de prédicats sur les variables du programme. Les valeurs abstraites sont des enen-sembles de valuations de ces prédicats, que l’on peut représenter par des formules propositionnelles sur ces prédicats. L’ensemble des valeurs abstraites est donc fini, ce qui a notamment pour avantage de permettre une analyse sans élargissement.

L’ensemble des prédicats peut être choisi par l’utilisateur ou automatiquement à partir du programme analysé. Il peut éventuellement varier selon les points de contrôle considérés. Ceci permet une grande généricité de l’analyse qui pourra donc s’appliquer à une grande classe de propriétés.

En contrepartie, cette généricité implique des difficultés à calculer une approximation cor-recte des fonctions de transfert. Les méthodes utilisées pour ce calcul reposent sur l’aide d’un démonstrateur de théorèmes. On leur demandera de démontrer si une formule utilisant les prédi-cats est impliquée par le résultat de l’application d’une fonction de transfert. Plusieurs méthodes ont été développées [DDP99, SS99] en se fixant pour but de minimiser le nombre d’appels au démonstrateur de théorème, mais la méthode reste coûteuse.

L’abstraction par prédicat peut être directement appliquée aux tableaux ou aux structures de données en considérant des prédicats contenant des quantificateurs. Par exemple en choisissant le prédicat (∀`, 1≤` <i⇒A[`]=0) on peut espérer vérifier un programme d’initialisation de tableau. D’ailleurs, ce prédicat est tellement particulier qu’il ne peut guère servir à autre chose. Mais demander à l’utilisateur de fournir de tels prédicats revient quasiment à lui demander de fournir les invariants de boucle. On n’est plus dans une optique de découverte de propriété. Par ailleurs tout le travail de vérification est en fait réalisé par le démonstrateur de théorème : on ne tire absolument pas profit du cadre défini par l’interprétation abstraite. Dès qu’on introduit des quantificateurs dans les prédicats, ces démonstrateurs doivent d’ailleurs être capables de travailler sur des formules du premier ordre.

Le problème en essence est que les quantificateurs doivent rester à l’intérieur des prédicats. Par conséquent, chaque prédicat utilise une variable quantifiée distincte. Ceci est très limitant dans la recherche d’invariants. Dans la suite de cette section nous énumérons diverses évolutions de l’abstraction par prédicats autorisant certaines classes de formules quantifiées sur les prédicats.

Les auteurs de [FQ02] proposent d’introduire des variables libres dans les prédicats. L’utilisa-teur fournit un ensemble de prédicats pouvant faire intervenir une ou plusieurs variables libres.