hardened golo: donnez de la confiance en votre code golo

31
HAL Id: hal-01354836 https://hal.inria.fr/hal-01354836 Submitted on 19 Aug 2016 HAL is a multi-disciplinary open access archive for the deposit and dissemination of sci- entiïŹc research documents, whether they are pub- lished or not. The documents may come from teaching and research institutions in France or abroad, or from public or private research centers. L’archive ouverte pluridisciplinaire HAL, est destinĂ©e au dĂ©pĂŽt et Ă  la diïŹ€usion de documents scientiïŹques de niveau recherche, publiĂ©s ou non, Ă©manant des Ă©tablissements d’enseignement et de recherche français ou Ă©trangers, des laboratoires publics ou privĂ©s. Hardened Golo : Donnez de la conïŹance en votre code Golo Raphael Laurent To cite this version: Raphael Laurent. Hardened Golo : Donnez de la conïŹance en votre code Golo. GĂ©nie logiciel [cs.SE]. 2016. hal-01354836

Upload: others

Post on 19-Jun-2022

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Hardened Golo: Donnez de la confiance en votre code Golo

HAL Id: hal-01354836https://hal.inria.fr/hal-01354836

Submitted on 19 Aug 2016

HAL is a multi-disciplinary open accessarchive for the deposit and dissemination of sci-entific research documents, whether they are pub-lished or not. The documents may come fromteaching and research institutions in France orabroad, or from public or private research centers.

L’archive ouverte pluridisciplinaire HAL, estdestinĂ©e au dĂ©pĂŽt et Ă  la diffusion de documentsscientifiques de niveau recherche, publiĂ©s ou non,Ă©manant des Ă©tablissements d’enseignement et derecherche français ou Ă©trangers, des laboratoirespublics ou privĂ©s.

Hardened Golo : Donnez de la confiance en votre codeGolo

Raphael Laurent

To cite this version:Raphael Laurent. Hardened Golo : Donnez de la confiance en votre code Golo. GĂ©nie logiciel [cs.SE].2016. ïżœhal-01354836ïżœ

Page 2: Hardened Golo: Donnez de la confiance en votre code Golo

Rapport de Projet de Fin d’ÉtudesHardened Golo: Donnez de la confiance en votre code Golo

Raphael Laurent

21 juin 2016

1

Page 3: Hardened Golo: Donnez de la confiance en votre code Golo

Table des matiĂšres1 Remerciements 3

2 Introduction 4

3 État de l’art 53.1 VĂ©rification statique de programmes . . . . . . . . . . . . . . . . 6

3.1.1 Preuve SMT . . . . . . . . . . . . . . . . . . . . . . . . . 63.1.2 Vérificateurs de programmes . . . . . . . . . . . . . . . . 73.1.3 Spécification JML . . . . . . . . . . . . . . . . . . . . . . 7

3.2 Analyse statique - en pratique . . . . . . . . . . . . . . . . . . . . 83.2.1 Langages intermédiaires . . . . . . . . . . . . . . . . . . . 83.2.2 Traduction de langages . . . . . . . . . . . . . . . . . . . 9

3.3 Bilan de cet Ă©tat de l’art . . . . . . . . . . . . . . . . . . . . . . . 9

4 Golo 10

5 ÉlĂ©ments de traduction Golo vers WhyML 105.1 Module et fonction . . . . . . . . . . . . . . . . . . . . . . . . . . 115.2 Appel de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . 115.3 DĂ©clarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135.4 Assignation sur une variable . . . . . . . . . . . . . . . . . . . . . 145.5 Consultation de constantes et variables . . . . . . . . . . . . . . . 145.6 OpĂ©rateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155.7 SpĂ©cification de programme . . . . . . . . . . . . . . . . . . . . . 165.8 Gestion du "return" . . . . . . . . . . . . . . . . . . . . . . . . . . 16

6 Implémentation 176.1 Grammaire JJTree et arbre syntaxique abstrait . . . . . . . . . . 186.2 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206.3 Fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216.4 Constantes et variables . . . . . . . . . . . . . . . . . . . . . . . . 23

7 Preuve dans Why3 24

8 Bilan 27

9 Retour d’expĂ©rience 28

2

Page 4: Hardened Golo: Donnez de la confiance en votre code Golo

1 RemerciementsJe tiens Ă  remercier mon tuteur Nicolas Stouls, pour ses conseils tout au long

de mon stage et son suivi rigoureux. Il m’a permis d’aller plus loin dans ma rĂ©ali-sation, ainsi que de comprendre diffĂ©rentes problĂ©matiques de mon sujet plus enprofondeur. Son encadrement m’a permis de structurer ce projet correctementet de garantir une contribution riche.

Je remercie Ă©galement Julien Ponge, pour ses indications Ă©clairĂ©es dans lefonctionnement du compilateur Golo, ainsi que le langage lui-mĂȘme.

Finalement, je remercie le laboratoire du CITI à l’INSA Lyon pour m’avoiraccueilli pendant ce stage.

3

Page 5: Hardened Golo: Donnez de la confiance en votre code Golo

2 IntroductionGolo [1] [2] est un langage dynamique construit autour de l’instruction "in-

vokedynamic" de la machine virtuelle Java. Originellement dĂ©veloppĂ© au labo-ratoire CITI de l’INSA de Lyon par le groupe Dynamid, Golo est open-sourceet dĂ©diĂ© Ă  la rĂ©alisation d’applications dynamiques.

L’objectif de mon stage est de pouvoir augmenter la confiance que l’on peutavoir en un programme Golo. L’approche retenue est d’utiliser l’outils Why3 [3]dĂ©veloppĂ© par l’équipe Toccata de l’INRIA/LRI/CNRS, originellement conçupour la vĂ©rification de programmes en C, Java et Ada. En s’appuyant sur letravail fait par le plugin Krakatoa [4] pour analyser du code Java avec cet outil,une traduction du code Golo vers du code WhyML [5] exĂ©cutable a Ă©tĂ© implĂ©-mentĂ©e dans le compilateur Golo. Cette implĂ©mentation vise Ă  poser une basepour pouvoir analyser statiquement du code Golo avec Why3, ainsi que pourfaire des vĂ©rifications statiques lors de la traduction. La spĂ©cification dans lecode Golo devait originellement se faire dans un langage inspirĂ© de JML [6],cependant l’approche implĂ©mentĂ©e permet au programmeur de spĂ©cifier le codeGolo dans le langage de spĂ©cification de Why3 directement. Le dĂ©tail de la mĂ©-thode d’implĂ©mentation, des fonctionnalitĂ©s supportĂ©es ainsi que des limitationssera abordĂ© dans une partie ultĂ©rieure.

Un travail prĂ©cĂ©dent sur le mĂȘme sujet rĂ©alisĂ© par Bertrand Cayeux montrequ’il est possible de modĂ©liser les objets dynamiques de Golo en Java. Il a Ă©tudiĂ©la possibilitĂ© de traduire Golo en Java pour prendre avantage du plugin Krakatoapour l’analyse statique en Java, comme montrĂ© sur la figure 1.

Figure 1 – Solution proposĂ©e par Bertrand Cayeux

Golo Java

Krakatoa

Why3 Prouveursexternes

Traduction Golovers Java

Traduction Javavers WhyML

Génération de conditionsde vérification

Cela peut inspirer une traduction similaire directement en WhyML par lasuite, cependant ce n’est pas abordĂ© dans mon travail qui vise Ă  mettre enplace les briques de base pour traduire Golo en WhyML pour faire de l’analysestatique, comme montrĂ© sur la figure 2.

4

Page 6: Hardened Golo: Donnez de la confiance en votre code Golo

Figure 2 – Solution proposĂ©e pour ce stage

Golo

Why3 ProuveursexternesTraduction Golo

vers WhyML Génération de conditionsde vérification

Dans un premier temps, je vais prĂ©senter un Ă©tat de l’art de la vĂ©rificationde programmes, et plus spĂ©cifiquement de la vĂ©rification statique.

3 État de l’artLa vĂ©rification de programmes a pour objectif de valider que le comportement

d’un programme est et sera celui attendu. Il existe diffĂ©rents langages de spĂ©ci-fication, avec chacun ses particularitĂ©s. Ainsi, les automates (ensemble d’étatset de transitions possibles) permettent d’exprimer une sĂ©quentialitĂ© d’actionset un ensemble d’état atteignables, les spĂ©cifications logiques permettent de dĂ©-crire la forme que doit avoir un paramĂštre ou un rĂ©sultat de calcul, les algĂšbresde processus permettent de mettre l’accent sur les communications et l’entre-lacement des actions dans les systĂšmes concurrents ou distribuĂ©s. Par ailleurs,les spĂ©cifications peuvent ĂȘtre placĂ©es dans des fichiers Ă  part entiĂšre ou bienliĂ©es fortement Ă  un code, comme c’est le cas des langage de spĂ©cification parannotation. Dans ce travail, nous verrons que c’est cette derniĂšre catĂ©gorie quinous intĂ©ressera plus particuliĂšrement.

Il y a ensuite trois méthodes générales pour valider un programme et saspécification, et toutes reposent sur la comparaison du comportement du pro-gramme au référentiel attendu défini au préalable :

— Tests : la vĂ©rification est opĂ©rĂ©e par l’exĂ©cution de cas spĂ©cifiques et deportions de code.

— Analyse dynamique : la vĂ©rification est opĂ©rĂ©e lors de l’exĂ©cution du pro-gramme dans un cas normal d’exĂ©cution. L’analyse dynamique est parfoiscombinĂ©e Ă  l’analyse statique pour pouvoir obtenir une information plusprĂ©cise sur l’origine d’une erreur de vĂ©rification [7].

— Analyse statique : les vĂ©rifications sont effectuĂ©es sur le programme sansexĂ©cution. L’une des maniĂšres de faire consiste Ă  rĂ©duire la combinaisondu programme et de son modĂšle Ă  un ensemble de conditions de vĂ©rifica-tions : aprĂšs analyse, si ces conditions sont validĂ©es alors le programmeest certifiĂ© comme valide, cependant un Ă©chec de vĂ©rification ne permetpas de diffĂ©rencier entre une erreur du programme et un manque d’infor-mation pour rĂ©soudre l’analyse.

Une diffĂ©rence significative parmi ces mĂ©thodes rĂ©side dans le fait que lestests et l’analyse dynamique nĂ©cessitent l’exĂ©cution de tout ou partie du pro-

5

Page 7: Hardened Golo: Donnez de la confiance en votre code Golo

gramme, alors que l’analyse statique permet de garantir le respect d’une spĂ©ci-fication pour toute exĂ©cution, et avant toute exĂ©cution.

Pouvoir garantir un fonctionnement avant exĂ©cution possĂšde de nombreuxavantages, notamment dans des environnements ou tester une application n’estpas sans danger (comme dans l’aĂ©ronautique par exemple). Cette approche estĂ©galement complĂ©mentaire aux tests ou Ă  l’analyse dynamique, et c’est pourquoile choix de travailler sur l’analyse statique a Ă©tĂ© fait.

Je vais maintenant détailler le fonctionnement de la vérification statique deprogrammes, et étudier les solutions existantes pour intégrer ces méthodes à deslangages orientés objets de haut niveau.

3.1 VĂ©rification statique de programmesJe m’intĂ©resse ici Ă  l’analyse statique de programmes en gĂ©nĂ©ral, et les diffĂ©-

rents outils qui la rendent possible. Je prĂ©sente d’abord briĂšvement le fonction-nement des prouveurs SMT, puis les outils qui les utilisent, avant de finir surla spĂ©cification de programmes, nĂ©cessaire pour pouvoir analyser statiquementdes programmes avec les outils prĂ©sentĂ©s.

3.1.1 Preuve SMT

Les prouveurs SMT (SatisfiabilitĂ© Modulo ThĂ©ories) tels que Alt-Ergo [8]sont le bloc de base de l’analyse statique. Leur objectif est de rĂ©soudre la satis-fiabilitĂ© de formules logiques (que l’on appelle ici conditions de vĂ©rifications), enfonction de prĂ©dicats Ă©noncĂ©s au prĂ©alable. A ce jour, les prouveurs sont limitĂ©sĂ  la logique de premier ordre, ce qui aura des rĂ©percussions sur certaines limita-tions de l’analyse statique prĂ©sentĂ©es plus loin. Notamment, cela implique quetout problĂšme du second ordre doit ĂȘtre ramenĂ© au premier ordre pour pouvoirĂȘtre rĂ©solu avec un prouveur SMT.

DiffĂ©rents prouveurs SMT ont diffĂ©rentes capacitĂ©s de rĂ©solution (mĂ©thodenaĂŻve, apprentissage de clauses par conflit, analyse de conflits, retour en arriĂšre).Cela implique que certaines formules peuvent ĂȘtre rĂ©solues par un prouveurSMT, alors que d’autres non. La conclusion directe que l’on peut en tirer estqu’utiliser diffĂ©rents prouveurs SMT peut donc amĂ©liorer le nombre de condi-tions de vĂ©rifications prouvables.

Bien que les prouveurs SMT puissent ĂȘtre utilisĂ©s manuellement pour vĂ©rifierdes formules logiques, ils sont principalement utilisĂ©s avec des outils qui gĂ©nĂšrentdes conditions de vĂ©rifications Ă  partir d’un programme et d’une spĂ©cification [9].Les conditions de vĂ©rification gĂ©nĂ©rĂ©es permettent d’assurer la logique suivante :

— Si la condition de vĂ©rification est vraie, alors le programme et la spĂ©cifi-cation sont vrais.

— Si la condition de vĂ©rification n’est pas vraie, alors on ne peut pas concluresur la justesse du programme et de sa spĂ©cification.

Toujours concernant la preuve SMT, on peut Ă©galement noter un effort pourautomatiser certaines tĂąches : la gĂ©nĂ©ration d’invariants automatiquement parexemple, pour dĂ©charger le programmeur de cette tĂąche parfois trĂšs complexe

6

Page 8: Hardened Golo: Donnez de la confiance en votre code Golo

[10]. Je m’intĂ©resse de plus prĂšs aux outils qui permettent la gĂ©nĂ©ration deconditions de vĂ©rifications automatiquement dans la partie suivante.

3.1.2 VĂ©rificateurs de programmes

Je prĂ©sente ici deux vĂ©rificateurs de programmes, qui sont tous deux basĂ©s surla traduction d’un langage intermĂ©diaire vers des conditions de vĂ©rifications pourprouveurs SMT. Nous reviendrons sur l’utilisation d’un langage intermĂ©diairedans la partie suivante.

Le premier outil est Why3 [3], dĂ©veloppĂ© par l’équipe Toccata de l’INRIA/L-RI/CNRS, originellement conçu pour la vĂ©rification de programmes en C, Javaet Ada. Le second outil est Boogie [11], dĂ©veloppĂ© par Microsoft Research, ori-ginellement conçu pour la vĂ©rification de programmes Spec#.

Ces outils ont en premier lieu de nombreux points communs :— Ils ont pour objectif principal d’automatiser la gĂ©nĂ©ration de conditions

de vĂ©rification pour des prouveurs SMT.— Ils se basent sur l’utilisation d’un langage intermĂ©diaire, ainsi qu’un lan-

gage de spĂ©cification (WhyML pour Why3, et Boogie2 pour Boogie).— Ils utilisent une modĂ©lisation explicite des structures et de la mĂ©moire.

L’utilisateur peut ainsi utiliser sa propre modĂ©lisation si besoin.— Ils travaillent en logique de premier ordre.Cependant, ils sont Ă©galement pensĂ©s diffĂ©remment, notamment sur deux

aspects que je considĂšre important pour le choix d’un outil pour ce stage :Boogie utilise Z3 comme prouveur SMT, alors que Why3 est dĂ©veloppĂ© autourdu support d’un grand nombre de prouveurs SMT, via un systĂšme de drivers.De plus, Boogie a Ă©tĂ© dĂ©veloppĂ© pour C# originellement, alors que Why3 pourC/Java. Sachant que Golo produit du bytecode qui s’exĂ©cute sur la machine vir-tuelle Java (comme Java), Why3 semble ĂȘtre un choix plus judicieux au premierabord.

Ces outils reposant tous sur la traduction d’un programme et d’une spĂ©ci-fication dans un langage intermĂ©diaire, nous allons d’abord Ă©tudier briĂšvementun langage de spĂ©cification, nĂ©cessaire pour pouvoir effectuer des vĂ©rificationplus poussĂ©es d’un programme par analyse statique.

3.1.3 Spécification JML

Dans ce travail, je m’intĂ©resse Ă  JML (Java Modelling Language) [6], uneinterface de spĂ©cification de comportement pour Java .

L’objectif principal de JML est de pouvoir masquer des modĂšles mathĂ©-matiques derriĂšre des classes facilement comprĂ©hensibles par tout program-meur Java. Le principe de base de ce langage de spĂ©cification est le "designpar contrat" : un tuple (obligations, bĂ©nĂ©fices) peut s’exprimer par un tuple(prĂ©-conditions, post-conditions). Ce langage utilise la logique de Hoare, lesprĂ©-conditions et post-conditions ainsi que les invariants, et permet l’ajout dequantifieurs, de variables de spĂ©cification pures (qui n’ont pas d’impact sur ledĂ©roulement du programme), et de "frame conditions" (dĂ©finit un comportement

7

Page 9: Hardened Golo: Donnez de la confiance en votre code Golo

normal et un comportement exceptionnel). JML peut ĂȘtre utilisĂ© pour gĂ©nĂ©rerdes docs amĂ©liorĂ©es, gĂ©nĂ©rer des tests unitaires, oĂč faire de la vĂ©rification sta-tique.

Pour pouvoir effectuer de l’analyse statique en Golo, il est nĂ©cessaire de semunir d’un langage de spĂ©cification. Golo Ă©tant similaire Ă  Java, une variante deJML pour spĂ©cifier le code Golo semble ĂȘtre une approche logique. Cependant,mon implĂ©mentation ne se concentre pas sur cet aspect et utilise directement lelangage de spĂ©cification de Why3 dans le code Golo.

3.2 Analyse statique - en pratiqueDans cette partie, je me concentre sur les langages intermédiaires des vérifi-

cateurs, ainsi que la traduction de langages. Il existe de nombreux exemples detraducteurs de langages, tel que Spoon [12], mais je me concentre ici uniquementsur ce qui touche aux langages intermĂ©diaires pour l’analyse statique.

3.2.1 Langages intermédiaires

Je m’intĂ©resse dans cette partie aux langages intermĂ©diaires, et plus particu-liĂšrement ceux utilisĂ©s avec les outils de vĂ©rification que sont Why3 et Boogie.

L’avantage d’un langage intermĂ©diaire pour un outil d’analyse statique estqu’il donne accĂšs Ă  toutes les fonctionnalitĂ©s de cet outil, tout en offrant unlangage de programmation et de spĂ©cification de haut niveau. Les trois langagesprĂ©sentĂ©s ici ont pour point commun de supporter quelques blocs de base pourĂ©crire un programme : constantes, variables mutables, code "ghost" (spĂ©cificationpure), sĂ©quences, boucles, fonctions, prĂ©/post-conditions, invariants.

Boogie2 (anciennement BoogiePL) est le langage utilisĂ© dans l’outil Boogie[11]. Il se dĂ©marque en Ă©tant un langage typĂ© dont le typage n’est pas forcĂ©("any" peut ĂȘtre utilisĂ© partout). Boogie2 supporte des procĂ©dures, mais pasde mĂ©thodes. Il n’y a Ă©galement pas de heap pour les objets, pas de classes nid’interfaces, les effets de bords ne sont pas permis, ni les appels par rĂ©fĂ©rence.Il n’y a pas d’exceptions ni de contrĂŽle de flow structurĂ©. Tous ces Ă©lĂ©mentsmanquants vont largement contribuer au choix de ne pas utiliser Boogie2 commelangage intermĂ©diaire par la suite, Ă©tant donnĂ© que Golo les utilisent tous (celasera discutĂ© dans la section suivante).

Dafny [13] est un autre langage intermĂ©diaire, qui lui est pensĂ© pour sup-porter la programmation orientĂ©e objet, avec cependant des limitations fortes,tel que l’absence d’hĂ©ritage. Le langage est typĂ©, et nĂ©cessite au programmeurde dĂ©clarer explicitement quelles parties du programme ont le droit de chan-ger (contrainte forte). Ce langage intermĂ©diaire est traduit en Boogie2 pourl’analyse dans l’outil Boogie.

Enfin, WhyML [5] est le langage intermĂ©diaire de l’outil Why3. Le langage esttypĂ©, cependant propose Ă©galement de l’infĂ©rence de type. Il ne possĂšde pas demodĂšle mĂ©moire, et supporte uniquement les alias statiques. Il n’y a Ă©galementpas d’objets, cependant ils peuvent ĂȘtre modĂ©lisĂ©s avec des structures de lalibrairie standard.

8

Page 10: Hardened Golo: Donnez de la confiance en votre code Golo

Les langages intermĂ©diaires peuvent ĂȘtre utilisĂ©s directement pour prouverdes algorithmes ou des thĂ©orĂšmes (bĂ©nĂ©ficier de la puissance des prouveurs SMTet en mĂȘme temps de langages de plus haut niveau), cependant ils sont Ă©galementbeaucoup utilisĂ©s comme langage de traduction cible. Nous allons regarder deplus prĂšs la traduction vers un langage intermĂ©diaire dans la partie suivante.

3.2.2 Traduction de langages

Dans cette section, je m’intĂ©resse Ă  la traduction de langages vers un langageintermĂ©diaire pour l’analyse statique. Je montre l’utilitĂ© de traduire vers un lan-gage intermĂ©diaire, bien qu’il y ait des limitations qui doivent ĂȘtre considĂ©rĂ©es.

Je considĂšre le travail fait pour traduire Dafny vers Boogie, Dafny Ă©tantconstruit autour de cette traduction [13]. La transformation cherche Ă  garantirqu’un programme Boogie2 prouvĂ© correct implique que le programme Dafnyd’origine est correct, cependant la garantie inverse n’est pas vraie : un pro-gramme Boogie2 qui ne vĂ©rifie pas ne permet pas de savoir Ă  coup sĂ»r quele programme Dafny est invĂ©rifiable. C’est une limitation assez importante :lorsqu’on "empile" les intermĂ©diaires entre le langage source et le langage dedestination, cela multiplie les possibilitĂ©s qu’un Ă©lĂ©ment non supportĂ© dans unetraduction d’un langage vers un autre apparaisse.

Un effort a Ă©galement Ă©tĂ© fait pour traduire Boogie2 vers WhyML [14] : l’idĂ©eĂ©tant de profiter de l’utilisation importante de Boogie dans le domaine de lavĂ©rification, tout en bĂ©nĂ©ficiant des avantages de Why3 permettant l’interfaçageavec de nombreux prouveurs externes. Un second avantage citĂ© rĂ©side dans lefait que le code WhyML peut ĂȘtre exĂ©cutĂ©. Il y a cependant des limitationsdues au fait que le systĂšme de typage de WhyML est plus restrictif que celui deBoogie2, tous les programmes ne peuvent pas ĂȘtre traduit avec succĂšs.

Finalement, le plugin Krakatoa pour Why3 [4] permet la traduction de pro-grammes Java annotĂ©s en JML vers des programmes WhyML. La mĂ©thode pro-pose notamment une dĂ©finition d’un modĂšle mĂ©moire dans le code, ainsi qu’unemodĂ©lisation des classes, deux Ă©lĂ©ments qui manquaient Ă  WhyML. Une des li-mitations du plugin rĂ©side dans le fait que le code WhyML produit est destinĂ©Ă  de la vĂ©rification pure, et ne peut pas ĂȘtre exĂ©cutĂ©.

Ces éléments viennent confirmer le choix de traduire directement de Golovers WhyML, tout en générant du code WhyML exécutable.

3.3 Bilan de cet Ă©tat de l’artCet Ă©tat de l’art me permet de justifier les choix d’implĂ©mentation d’une

solution pour augmenter la confiance en du code Golo. L’approche choisie sebase sur l’outil d’analyse statique Why3, en utilisant WhyML comme langagecible d’une traduction directe depuis Golo. La spĂ©cification est faite directementavec le langage de spĂ©cification de Why3 dans le code Golo. L’analyse statiquepeut ensuite ĂȘtre effectuĂ©e dans Why3 avec des prouveurs externes. QuelquesĂ©lĂ©ments de vĂ©rification sont prĂ©sents dans le traducteur directement (syntaxe

9

Page 11: Hardened Golo: Donnez de la confiance en votre code Golo

Golo, existence de fonction). Le code WhyML produit est exĂ©cutable, et produitles mĂȘme rĂ©sultats que le code Golo.

Dans la partie suivante, je m’intĂ©resse plus en dĂ©tail au langage Golo et Ă ses spĂ©cificitĂ©s. Je dĂ©taillerai ensuite la traduction de certains Ă©lĂ©ments de Golovers WhyML, avant d’expliquer des Ă©lĂ©ments clĂ©s de mon implĂ©mentation dansle compilateur Golo.

4 GoloGolo [1] [2] est un langage simple pour la machine virtuelle Java (JVM),

crĂ©Ă© pour la recherche et l’éducation. Le trait principal de ce langage est lefait qu’il est construit autour de l’instruction invokedynamic de la JVM 7+.Invokedynamic permet notamment de customiser Ă  l’exĂ©cution un lien entreun site d’appel et une implĂ©mentation de mĂ©thode. Cette instruction simplifiegrandement la crĂ©ation d’un langage typĂ© dynamiquement pour la JVM.

Golo est similaire Ă  Java sur beaucoup d’aspects, et supporte mĂȘme l’APIJava standard : les librairies Java peuvent ĂȘtre utilisĂ©es en Golo. Les Ă©lĂ©mentstels que les boucles et le contrĂŽle de flux sont similaires Ă©galement. Cependant,le langage vise Ă  offrir une dynamicitĂ© qui n’est pas atteignable facilement enJava. Pour cela, Golo offre notamment :

— L’augmentation de classes : permet d’ajouter des mĂ©thodes Ă  une classedynamiquement.

— Les objets dynamiques : des objets dont les propriĂ©tĂ©s et les mĂ©thodespeuvent ĂȘtre dĂ©finis pour chaque instance.

— Un typage dynamiqueJe montre dans la partie suivante comment certains Ă©lĂ©ments de Golo peuvent

ĂȘtre traduits en WhyML.

5 ÉlĂ©ments de traduction Golo vers WhyMLJe montre ici comment peuvent ĂȘtre traduits des Ă©lĂ©ments de Golo enWhyML,

un langage proche syntaxiquement de OCaml, pour l’outil Why3. J’ajoute lacontrainte que le code WhyML soit exĂ©cutable, ce qui permet de vĂ©rifier facile-ment sur un programme simple que le comportement est le mĂȘme qu’en Golo,et permet d’identifier de possibles erreurs qui apparaissent uniquement Ă  l’exĂ©-cution, tout cela sans complexifier la traduction de façon importante. Je meconcentre sur les fonctionnalitĂ©s gĂ©nĂ©rales des Ă©lĂ©ments traduits, l’objectif Ă©tantde pouvoir poser les bases pour la traduction d’un programme simple. Les Ă©lĂ©-ments traduits ne supportent pas toutes les fonctionnalitĂ©s Golo, l’objectif Ă©tantde pouvoir traduire un nombre suffisant d’élĂ©ments pour la traduction automa-tique de programmes simples (plus de fonctionnalitĂ©s peuvent ĂȘtre ajoutĂ©es parla suite une fois les bases posĂ©es).

L’ensemble des Ă©lĂ©ments pour lesquels une traduction est visĂ©e est composĂ©de : module, fonction, variables, opĂ©rateurs, spĂ©cification, return. Ces Ă©lĂ©ments

10

Page 12: Hardened Golo: Donnez de la confiance en votre code Golo

ne sont parfois traduits que partiellement, comme prĂ©cisĂ© dans les parties sui-vantes qui montrent comment traduire des portions de code Golo en WhyML.Dans la section ??, je prĂ©senterai l’outil dĂ©veloppĂ© dans le cadre de ce travail,qui implĂ©mente les Ă©lĂ©ments prĂ©sentĂ©s ici.

5.1 Module et fonctionLes fonctions Golo font toujours parties d’un module, Ă©lĂ©ment de base de

tout programme. Le code 1 montre la dĂ©finition d’un module et d’une fonctionsimple, renvoyant son premier paramĂštre. Une fonction Golo est dĂ©finie avec lemot clĂ© "function", et les paramĂštres sont listĂ©s entre deux symboles "|".

1 module fonction.Main2

3 function main = |a, b| {4 return a5 }

Code 1: Module Golo

Le code WhyML correspondant 2 est trĂšs similaire. Une dĂ©claration de fonc-tion peut se faire avec le mot clĂ© "let", et les paramĂštres apparaissent entreparenthĂšses. Notons qu’en WhyML le rĂ©sultat de la derniĂšre instruction d’unefonction est la valeur retournĂ©e implicitement.

En raison de limitations de la ligne de commande Why3, ce code WhyMLn’est pas directement exĂ©cutable car il n’est pas possible de lancer un programmepar une fonction attendant des paramĂštres.

1 module FonctionMain2 let main (a)(b)3 = a4 end

Code 2: Module WhyML

Je considĂšre tout au long de ce travail que nous nous intĂ©ressons Ă  un uniquemodule Golo (dans un seul fichier). Je montre dans la prochaine partie commentpeut ĂȘtre traduit un appel de fonction, et ne traite donc pas le cas des fonctionsappartenant Ă  un autre module.

5.2 Appel de fonctionUn appel de fonction en Golo peut se faire de plusieurs façon :— Appel de fonction sans paramùtre— Appel de fonction avec paramùtres

11

Page 13: Hardened Golo: Donnez de la confiance en votre code Golo

— Appel de fonction avec aritĂ© variable— Appel de fonction avec des paramĂštres nommĂ©s : permet d’utiliser le nom

des paramĂštres explicitement lors de l’appel d’une fonction (permet ainside rĂ©-ordonner les paramĂštres Ă  l’appel).

Je m’intĂ©resse ici Ă  montrer comment implĂ©menter en WhyML un appel defonction avec ou sans paramĂštres pour pouvoir supporter une grande quantitĂ©de programmes simples. WhyML ne permettant pas les appels de fonctions Ă aritĂ© variable, il faut adapter les appels de fonction lors de la traduction pourque l’aritĂ© de l’appel dans le code WhyML corresponde Ă  l’aritĂ© de la fonctionappelĂ©e.

L’exemple Golo du code 3 montre comment une fonction peut ĂȘtre appelĂ©eavec un paramĂštre. L’équivalent en WhyML dans le code 4 affiche une syntaxesimilaire.

1 function test = |a| {2 return a3 }4

5 function appel_test = {6 test(1) # renvoie 17 }

Code 3: Appel de fonction Golo

1 let test (a) =2 (a)3

4 let appel_test =5 test (1) (* renvoie 1 *)

Code 4: Appel de fonction WhyML

Les appels de fonctions en Golo peuvent gĂ©nĂ©rer des crashs au moment del’exĂ©cution si une fonction appelĂ©e n’existe pas. Je m’intĂ©resse donc ici Ă  vĂ©rifierstatiquement l’existence d’une fonction lors d’un appel. Cette vĂ©rification estopĂ©rĂ©e directement lors de la traduction, et est dĂ©taillĂ©e dans la description demon implĂ©mentation.

Une difficultĂ© importante de la traduction des appels de fonctions vient dufait que les fonctions en WhyML on besoins d’ĂȘtre dĂ©finies avant d’ĂȘtre utilisĂ©esdans le code, alors que ce n’est pas le cas en Golo. Il est possible d’utiliserdes prototypes en WhyML pour les cas ou les fonctions sont dĂ©finies aprĂšs ĂȘtreappelĂ©es, cependant il est nĂ©cessaire de prĂ©ciser les types des paramĂštres ainsique le type de retour de la fonction. Je montre dans le code 5 un exemple deprototype.

12

Page 14: Hardened Golo: Donnez de la confiance en votre code Golo

1 val test (a: int): int (* prototype *)2

3 let appel_test =4 test (1) (* renvoie 1 *)5

6 let test (a) =7 (a)

Code 5: Prototype WhyML

Un autre Ă©lĂ©ment nĂ©cessaire Ă  tout programme Golo simple est la dĂ©clarationde constantes et variables. Je m’intĂ©resse Ă  leur traduction en WhyML dans lapartie suivante.

5.3 DéclarationsGolo fait la différence entre les variables et les constantes. Le compilateur

possĂšde dĂ©jĂ  un certain nombre de vĂ©rification statiques Ă  ce niveau, tel quela vĂ©rification qu’une constante n’est pas modifiĂ©e : il n’est donc pas nĂ©cessairede rĂ©-implĂ©menter ces vĂ©rifications. Un autre Ă©lĂ©ment clĂ© est le fait que toutevariable ou constante dĂ©clarĂ©e dans un programme Golo doit ĂȘtre initialisĂ©e :une dĂ©claration va toujours de pair avec une assignation, dont la traduction estdĂ©taillĂ©e dans la partie suivante.

Un exemple de dĂ©claration d’une constante et d’une variable est montrĂ© dansle code 6 .

1 let myCons = 12 var myVar = 2

Code 6: DĂ©clarations Golo

L’équivalent Ă  ce code Golo peut ĂȘtre Ă©crit en WhyML comme montrĂ© dansle code 7 .

1 import ref.Ref2 (* ... *)3 let myCons = 1 in4 let myVar = ref 2 in

Code 7: DĂ©clarations WhyML

Les variables WhyML sont en rĂ©alitĂ© des rĂ©fĂ©rences (de la librairie standardref.Ref) avec un Ă©lĂ©ment mutable. Cela implique que l’assignation d’une nouvelle

13

Page 15: Hardened Golo: Donnez de la confiance en votre code Golo

valeur Ă  une variable se fait diffĂ©remment que l’assignation lors de la dĂ©claration,dĂ©taillĂ© dans la prochaine partie.

5.4 Assignation sur une variableJe dĂ©cris ici comment l’assignation d’une nouvelle valeur Ă  une variable est

faite. Nous avons vu dans la partie prĂ©cĂ©dente l’assignation lors de la dĂ©claration,je ne reviens donc pas déçu.

Je montre dans le code 8 comment assigner une nouvelle valeur Ă  une rĂ©fĂ©-rence WhyML. Il faut noter ici une limitation importante de WhyML : lors dela dĂ©claration d’une rĂ©fĂ©rence, un type est dĂ©fini (implicitement), il n’est doncpas possible d’assigner un Ă©lĂ©ment d’un type diffĂ©rent Ă  cette variable. GoloĂ©tant dynamiquement typĂ© et permettant ce comportement, je propose une al-ternative pour pouvoir traduire un code Ă©quivalent en WhyML : re-dĂ©clarer lavariable avec le nouveau type, comme montrĂ© dans le code 9 . Il faut cependantfaire attention Ă  la portĂ©e de la nouvelle dĂ©claration qui peut ĂȘtre moindre quela dĂ©claration originale, ainsi qu’aux cas ou des effets de bords disparaĂźtraientĂ  cause de la redĂ©finition.

1 import ref.Ref2 (* ... *)3 let myVar = ref 2 in4 myVar := 5 (* myVar est maintenant 5 *)

Code 8: Assignation WhyML

1 import ref.Ref2 (* ... *)3 let myVar = ref (1, 2) in (* myVar est un tuple d’int *)4 let myVar = ref 5 in (* myVar est maintenant un int *)

Code 9: Assignation WhyML avec type différent

Je montre dans la partie suivante comment peuvent ĂȘtre utilisĂ©es des va-riables et constantes (accĂšs en lecture).

5.5 Consultation de constantes et variablesEn Golo, la lecture d’une constante ou d’une variable est effectuĂ©e de la mĂȘme

maniĂšre, il suffit d’utiliser le nom de cette constante/variable pour y accĂ©der.En WhyML cependant, les variables Ă©tant construites avec des rĂ©fĂ©rences, leurmĂ©thode d’accĂšs est diffĂ©rente des constantes pour lequel utiliser le nom (commeen Golo) est suffisant.

14

Page 16: Hardened Golo: Donnez de la confiance en votre code Golo

Je montre dans le code 10 comment accĂ©der Ă  la valeur d’une variable enWhyML. Ce constat d’un accĂšs diffĂ©rent entre constantes et variable a un im-pact lors de l’implĂ©mentation du traducteur, car un accĂšs ne se traduira pas dela mĂȘme façon en fonction du type d’élĂ©ment accĂ©dĂ©. Je dĂ©taille cette problĂ©-matique dans la description de mon implĂ©mentation.

1 import ref.Ref2 (* ... *)3 let myVar = ref 1 in4 !myVar (* renvoie la valeur 1 *)

Code 10: AccĂšs Ă  une variable en WhyML

Dans la partie suivante je montre comment effectuer des opérations simplessur ces éléments, avec le support de quelques opérateurs.

5.6 OpérateursParmi les fonctionnalités de base du langage Golo figurent les opérateurs. Ils

sont au nombre de dix 1, et je vise ici Ă  traduire les plus communs (opĂ©rationset comparaisons numĂ©riques) pour poser une premiĂšre base, la traduction desautres opĂ©rateurs pouvant ĂȘtre Ă©tudiĂ©e ultĂ©rieurement.

Le problĂšme de traduction des opĂ©rateurs est en rĂ©alitĂ© plus complexe qu’iln’y parait au premier abord en raison du typage strict de WhyML, et du fait qu’iln’est pas possible de surcharger une fonction en WhyML. Ainsi, l’opĂ©rateur "+"en Golo peut effectuer une addition sur des nombres et des chaĂźnes de caractĂšres,cependant en WhyML chaque opĂ©ration sur des types diffĂ©rents doit ĂȘtre dĂ©finiedans des fonctions diffĂ©rentes. J’ai donc dĂ©cidĂ© de restreindre le problĂšme auxopĂ©rations sur les nombres entiers (int) dans un premier temps, pour simplifierle traitement de la traduction.

La libraire standard WhyML propose une implĂ©mentation des opĂ©rateursde base dans diffĂ©rentes thĂ©ories. Certaines de ces thĂ©ories viennent ajouter desvĂ©rifications statiques, comme la division dĂ©finie dans "mach.int" qui ajoute uneprĂ©-condition sur le dĂ©nominateur (doit ĂȘtre non-nul). L’utilisation de ces thĂ©o-ries permet dĂ©jĂ  d’ajouter des vĂ©rifications statiques sur du code sans spĂ©cifica-tion. Le code 11 montre un exemple de code WhyML d’une division arithmĂ©tiqued’entiers.

Dans le cas d’une fonction effectuant une division, et avec une dĂ©finition dela division ajoutant une prĂ©-condition sur le dĂ©nominateur, il faut permettre auprogrammeur d’ajouter de la spĂ©cification au programme pour que Why3 puissevalider le code. Je dĂ©taille dans la partie suivante comment la spĂ©cification esttraduite entre Golo et WhyML.

1. addition numĂ©rique et de chaĂźnes de caractĂšres, soustraction numĂ©rique, multiplicationnumĂ©rique et de chaĂźnes de caractĂšres, division numĂ©rique, modulo numĂ©rique, comparaisonnumĂ©rique et d’objets, comparaison de qualitĂ© de rĂ©fĂ©rences, opĂ©rateur boolĂ©en, vĂ©rificationde type, valeur si null

15

Page 17: Hardened Golo: Donnez de la confiance en votre code Golo

1 import mach.int2 (* ... *)3 let a = 4 in4 let b = 2 in5 let c = Int.(/) a b in (* c = 2 *)

Code 11: Division WhyML

5.7 SpĂ©cification de programmePour pouvoir spĂ©cifier le code Golo, j’ai choisi d’utiliser directement la spĂ©ci-

fication de l’outil Why3 en Golo, la syntaxe Ă©tant claire et simple Ă  comprendre.Il n’y a ainsi pas de traduction Ă  faire, il s’agit simplement de pouvoir parserla spĂ©cification (l’implĂ©mentation dans le parseur est dĂ©taillĂ©e dans une partiesuivante). Je choisi d’utiliser des balises "spec/" et "/spec" pour placer la spĂ©cifi-cation, ce qui simplifie la lecture et Ă©vite le mĂ©lange avec le code Golo exĂ©cutable.Le code 12 montre un exemple d’une fonction avec de la spĂ©cification.

1 function max = |a, b| spec/ ensures{ (result >= a) /\2 (result >=b) /\3 (forall z:int. z>=a /\ z>=b -> z >= result) }4 /spec {5 if(a >= b) {6 return (a)7 } else {8 return (b)9 }

10 }

Code 12: Spécification dans Golo

Il faut noter ici que la spĂ©cification Why3 fait correspondre directementla valeur de retour d’un programme Ă  la variable de spĂ©cification "result". Ilfaut donc Ă©viter d’utiliser des variables ou constantes appelĂ©es "result" dans leprogramme, ce qui pourrait crĂ©er des conflits lors de l’analyse statique (unealternative Ă©tant de renommer lors de la traduction).

Un Ă©lĂ©ment manquant pour pouvoir traduire des programmes simples enGolo est une gestion de "return", c’est Ă  dire pouvoir retourner une valeur etquitter une fonction avant la fin de celle-ci. Je dĂ©taille comment traduire celaen WhyML dans la partie suivante.

5.8 Gestion du "return"Une fonction Golo renvoie toujours une valeur. Si une fonction ne renvoie rien

explicitement, alors la valeur "null" est renvoyée. De plus, comme dans la plupart

16

Page 18: Hardened Golo: Donnez de la confiance en votre code Golo

des langages de programmation orientĂ©s objets, il est possible de renvoyer unevaleur avant la fin d’une fonction, sans exĂ©cuter le reste. WhyML ne possĂšdepas de "return", et pour pouvoir dĂ©finir un comportement identique j’utilise lemĂ©canisme d’exceptions, ainsi que la variable "return" qui est utilisĂ©e par dĂ©fautpour dĂ©finir la valeur de retour d’une fonction.

Je rappelle ici que je prends le cas particulier d’une fonction qui ne peutrenvoyer que des entiers. Pour pouvoir traduire les fonctions qui ne renvoientpas de valeur explicitement, je dĂ©fini Ă©galement une nouvelle constante de typenull. Un exemple de fonction avec une valeur de retour est montrĂ© dans le code13 (cette fonction renvoie null si a >= 10, ou a sinon).

1 exception Return ()2 constant null : int3

4 let lowerThanTen (a) =5 let return = ref 0 in try begin (6 if (Int.(≄) a 10) then (7 return := null; (* attribue la valeur null Ă  return *)8 raise Return ) (* raise l’exception *)9 else (

10 return := a;11 raise Return )12 ) end with Return → !return (* exception renvoie valeur de

return *)

Code 13: Return WhyML

Les Ă©lĂ©ments de base de la traduction de Golo vers WhyML Ă©tant posĂ©s, jedĂ©cris dans la partie suivante l’implĂ©mentation qui a Ă©tĂ© faite dans le compilateurGolo.

6 ImplĂ©mentationL’implĂ©mentation de la traduction automatique de code Golo vers du code

WhyML est faite directement dans le compilateur Golo, qui est écrit en Java.La version utilisée pour le développement est le snapshot 3.2.0-M1.

La traduction de code Golo pour la vĂ©rification statique dans l’outil Why3Ă©tant un nouvel Ă©lĂ©ment du compilateur, une nouvelle commande appelĂ©e "goloverify" lui est associĂ©. Dans la figure 3 apparaissent les Ă©lĂ©ments principaux dela fonction "golo verify" implĂ©mentĂ©e pendant ce stage.

17

Page 19: Hardened Golo: Donnez de la confiance en votre code Golo

Figure 3 – ÉlĂ©ments clĂ©s de Golo Verify

GoloVerify Parseur

ArbreSyntaxiqueAbstrait

ReprésentationIntermédiaire

VisiteurReprésentationIntermédiaire

CodeWhyML

Le compilateur Golo utilise un gĂ©nĂ©rateur de parseur qui se base sur unedĂ©finition de grammaire pour gĂ©nĂ©rer un arbre syntaxique abstrait. Une fois cetarbre gĂ©nĂ©rĂ©, des visiteurs le parcourent pour effectuer quelques vĂ©rifications(par exemple, tester si une constante n’est pas rĂ©-assignĂ©e), ainsi que pour dĂ©-sugariser le code. Cela produit une reprĂ©sentation intermĂ©diaire qui reprĂ©senteles Ă©lĂ©ments Golo sous forme d’objets Java.

Mon implĂ©mentation est concentrĂ©e en grande partie sur la reprĂ©sentationintermĂ©diaire, aprĂšs l’appel Ă  des visiteurs sur l’arbre abstrait. Travailler surcette reprĂ©sentation intermĂ©diaire a Ă©galement pour avantage de respecter lelangage Golo sans avoir Ă  rĂ©-implĂ©menter la sĂ©mantique, contrairement Ă  l’arbresyntaxique abstrait qui lui est issu du parseur et n’a pas Ă©tĂ© validĂ©. Je dĂ©crisdans les parties suivantes les Ă©lĂ©ments clĂ©s de l’implĂ©mentation rĂ©alisĂ©e, ainsique leurs implications.

6.1 Grammaire JJTree et arbre syntaxique abstraitPour pouvoir ajouter un nouveau type de code Golo qui soit reconnu par

le parseur, il faut modifier la dĂ©finition de la grammaire Golo. Le compilateurutilise JJTree, un prĂ©-processeur pour JavaCC qui gĂ©nĂšre un parseur Ă  partird’une dĂ©finition de grammaire. Ce parseur produit ensuite un arbre syntaxiqueabstrait.

Dans un premier temps, pour reconnaßtre un bloc de spécification, un nou-veau token SPEC est défini comme montré dans le code jjt 14 .

Ce token est utilisé pour récupérer directement la spécification dans unString, comme montré dans le code 15 .

Cet Ă©lĂ©ment de spĂ©cification est appelĂ© dans la dĂ©finition d’une fonction, quiest actuellement le seul endroit ou l’on est autorisĂ© Ă  mettre de la spĂ©cificationdans le code Golo. Pour pouvoir supporter de la spĂ©cification n’importe ou dansle code, il faudrait dĂ©finir un nouveau noeud pour l’arbre abstrait ainsi que pourla reprĂ©sentation intermĂ©diaire pour la spĂ©cification.

Dans les parties suivantes, je dĂ©taille l’implĂ©mentation de quelques Ă©lĂ©mentsdu visiteur de la reprĂ©sentation intermĂ©diaire qui s’occupe de gĂ©nĂ©rer la traduc-

18

Page 20: Hardened Golo: Donnez de la confiance en votre code Golo

MORE :{ < " spec /" > : WithinSpec }

<WithinSpec>TOKEN :{ < SPEC : "/ spec " > : DEFAULT }

<WithinSpec>MORE :{ < ~ [ ] > }

Code 14: Token SPEC

Str ing S p e c i f i c a t i o n ( ) #void :{Token specToken ; }{ specToken = <SPEC>

{ return specToken . image . sub s t r i ng (5 ,specToken . image . l ength ()−5) . tr im ( ) ; }

}

Code 15: Token SPEC

tion en WhyML.

19

Page 21: Hardened Golo: Donnez de la confiance en votre code Golo

6.2 ModuleL’implĂ©mentation de la traduction d’un module est un bon exemple pour

montrer comment le visiteur de la reprĂ©sentation intermĂ©diaire fonctionne. Lafonction "visitModule" est la premiĂšre appelĂ©e et est donc le point d’entrĂ© dela traduction. Les Ă©lĂ©ments les plus importants de cette fonction sont montrĂ©sdans le code 16 .

"whyMLcode" est un ArrayList de String qui permet de stocker le codeWhyML gĂ©nĂ©rĂ©. La ligne 2 dĂ©clare le module en WhyML, et les lignes 4 Ă  9ajoutent dans le code WhyML les imports de base pour les fonctions qui sontactuellement supportĂ©es, ainsi que les dĂ©clarations de l’exception Return et dela constante "null". Une amĂ©lioration nĂ©cessaire sur cette partie serait d’enleverles imports statiques, et de les ajouter lorsqu’ils sont nĂ©cessaires (par exemple,importer mach.int.Int uniquement si des opĂ©rations arithmĂ©tiques sont effec-tuĂ©es).

La ligne 11 appel le visiteur sur la totalitĂ© du contenu du module. Une fois laligne 11 exĂ©cutĂ©e, le code du module est normalement entiĂšrement traduit, et laligne 12 vient marquer la fin du module. Le bloc try/catch Ă©crit le code gĂ©nĂ©rĂ©dans le fichier de destination. Finalement, un dernier test est effectuĂ© avant dequitter le visiteur Ă  la ligne 18 : les dĂ©finitions de fonctions ainsi que les appelsde fonctions ont Ă©tĂ© enregistrĂ©s durant la visite, et ce test vĂ©rifie l’existence detoute fonction appelĂ©e. Une des limitations actuelles de cette implĂ©mentationest le fait que les fonctions intĂ©grĂ©es de base ne sont pas gĂ©rĂ©es (cependant,leur traduction non plus, il est donc raisonnable d’afficher une erreur). CettevĂ©rification fonctionne Ă©galement lorsqu’une fonction est appelĂ©e avec une aritĂ©supĂ©rieure Ă  celle de la fonction dĂ©finie, Ă©tant donnĂ© que Golo rend cela possible.

Étant donnĂ© qu’un module est trĂšs souvent suivi de la dĂ©finition d’une fonc-tion, je prĂ©sente dans la partie suivante l’implĂ©mentation de la traduction d’unefonction.

20

Page 22: Hardened Golo: Donnez de la confiance en votre code Golo

1 /* ... */2 whyMLcode.add("module " + moduleName)3 /* ... */4 whyMLcode.add(space() + "use import int.Int");5 whyMLcode.add(space() + "use import ref.Ref");6 whyMLcode.add(space() + "use import mach.int.Int");7 whyMLcode.add(space() + "type null");8 whyMLcode.add(space() + "constant null : int");9 whyMLcode.add(space() + "exception Return ()");

10

11 module.walk(this);12 whyMLcode.add(space() +"end");13 try {14 Files.write(Paths.get(destFile), whyMLcode, Charset.forName("UTF-8"));15 } catch (IOException e) {16 e.printStackTrace();17 }18 testFunctionsCalledExist();

Code 16: ÉlĂ©ments de la fonction visitModule

6.3 FonctionLa traduction d’une fonction est un Ă©lĂ©ment un peu plus complexe que la

simple définition du module. Le code est donc présenté par morceau pour desraisons de clarté.

Les premiers Ă©lĂ©ments d’une fonction, dĂ©crits dans le code 17 montrent prin-cipalement l’ajout de la fonction Ă  la liste des fonctions dĂ©clarĂ©es (ligne 1, 2),puis la dĂ©claration de la fonction dans le code WhyML (ligne 3 et 5). La ligne4 vient ajouter les nombres de lignes auxquelles cette fonction apparaĂźt dans lefichier Golo pour les afficher dans l’outil Why3. On peut remarquer que l’im-plĂ©mentation est lĂ©gĂšrement diffĂ©rente de la traduction d’une fonction dĂ©finiedans la partie thĂ©orique prĂ©cĂ©dente : l’utilisation de "let function = fun ->" estnĂ©cessaire pour pouvoir insĂ©rer les numĂ©ros de lignes.

1 functionsDefined.add(new functionNameArity(function.getName(),2 function.getArity()));3 whyMLcode.add(space() + "let " + function.getName() + " ");4 appendWhyMLLastString(getSourceCodeBlocksLines(function) + " = ");5 whyMLcode.add(space() + "fun ");

Code 17: DĂ©finition de fonction

Le code 18 montre la traduction des paramĂštres de la fonction. Deux cas

21

Page 23: Hardened Golo: Donnez de la confiance en votre code Golo

sont possibles : si la fonction possÚde des paramÚtres, ceux-ci sont ajoutés entreparenthÚses, sinon des parenthÚses vides sont écrites. Cet ajout est nécessaireà WhyML, une fonction sans paramÚtre en Golo ne nécessitant pas de balisesvides. La derniÚre ligne vient copier la spécification (si présente) depuis ce quia été parsé directement dans le code WhyML.

1 for (String param : function.getParameterNames()) {2 appendWhyMLLastString("( " + param + " )");3 }4 if (function.getParameterNames().isEmpty()){5 appendWhyMLLastString("()");6 }7 whyMLcode.add(space()+function.getSpecification());

Code 18: ParamĂštres de la fonction

Le code 19 montre la dĂ©claration des rĂ©fĂ©rences locales, effectuĂ©es avant lecorps de la fonction. Cette implĂ©mentation est nĂ©cessaire, les variables (rĂ©fĂ©-rences) en WhyML nĂ©cessitant d’ĂȘtre dĂ©clarĂ©es avant leur initialisation/utili-sation. Il y a une limitation majeure cependant : la portĂ©e des variables estautomatiquement toute la fonction. Ainsi, une variable qui en Golo ne serait vi-sible qu’à l’intĂ©rieur d’une boucle est visible en WhyML dans la fonction entiĂšreavec cette implĂ©mentation. Des vĂ©rifications additionnelles sur la rĂ©utilisationdes noms de variables ainsi que sur l’existence d’une variable sachant sa portĂ©esont nĂ©cessaire pour rendre l’implĂ©mentation complĂštement correcte.

1 LinkedList<LocalReference> refList = function.returnOnlyReference(this);2 for (LocalReference ref: refList) {3 boolean isParam = false;4 for (String param: function.getParameterNames()){5 if (ref.getName().equals(param)) {6 isParam = true;7 }8 }9 if(!isParam && !ref.isConstant()){

10 whyMLcode.add(space() + "let " + ref.getName() + " = ref 0 in ");11 }12 }

Code 19: Déclaration des références locales

Finalement, le code 20 montre les derniers Ă©lĂ©ments de la traduction d’unefonction : la rĂ©fĂ©rence return est dĂ©clarĂ©e en ligne 1, avant de lancer la visite ducorps de la fonction (et donc la gĂ©nĂ©ration de sa traduction). La ligne 3 vientfermer la fonction et ajouter l’exception qui gĂšre l’appel Ă  "return".

22

Page 24: Hardened Golo: Donnez de la confiance en votre code Golo

1 whyMLcode.add(space() + "let return = ref 0 in try begin");2 function.walk(this);3 whyMLcode.add(space() + "; end with Return -> !return end");

Code 20: Return et corps de la fonction

6.4 Constantes et variablesDans la présentation théorique de la traduction, une difficulté autour de la

gestion diffĂ©rente des constantes et variables en WhyML, comparĂ© Ă  Golo, avaitĂ©tĂ© relevĂ©e. Je montre ici comment l’implĂ©mentation de la traduction permet derĂ©soudre ces diffĂ©rences.

Dans un premier temps, lors d’une assignation, il suffit de gĂ©rer deux caspour que la traduction gĂ©nĂšre du code WhyML correct. Ces cas sont montrĂ©sdans le code 21. Dans le cas ou la rĂ©fĂ©rence est dĂ©finie comme constante dans lareprĂ©sentation intermĂ©diaire, le code "let refName =" est gĂ©nĂ©rĂ© avant de visiterce qui est assignĂ© avec la fonction "walk". Sinon, la rĂ©fĂ©rence est donc variableet l’opĂ©rateur " := " est utilisĂ© avant de visiter l’élĂ©ment assignĂ©.

1 if (assignmentStatement.getLocalReference().isConstant()) {2 whyMLcode.add(space() + "let " + refName + " = ");3 assignmentStatement.walk(this);4 whyMLcode.add(space() + " in");5 } else {6 whyMLcode.add(space() + "( " + refName + " := ");7 assignmentStatement.walk(this);8 whyMLcode.add(space() + " );");9 }

Code 21: Assignation de constantes et variables

D’une façon similaire lors de la lecture d’une constante ou variable, le code22 montre le mĂȘme type de procĂ©dĂ© pour sĂ©parer les deux cas possibles : copieruniquement le nom de la constante dans le code WhyML, ou ajouter " !" devants’il s’agit d’une variable.

1 if (reference.isConstant()) {2 whyMLcode.add(space() + "( " + referenceLookup.getName() + " ) ");3 } else {4 whyMLcode.add(space() + "( !" + referenceLookup.getName() + " ) ");5 }

Code 22: Lecture de constantes et variables

23

Page 25: Hardened Golo: Donnez de la confiance en votre code Golo

Les autres Ă©lĂ©ments sont traduits avec des mĂ©thodes similaires et ne sont doncpas dĂ©taillĂ©s dans ce rapport (le code source complet Ă©tant fourni). Je montredans la prochaine partie quelques exemples de programmes Golo traduits enWhyML et analysĂ©s dans l’outil Why3.

7 Preuve dans Why3Je montre dans cette partie des exemples de code Golo analysĂ©s dans l’outil

Why3. L’objectif est de pouvoir identifier quelques applications rendues possiblepar ma contribution.

Le premier exemple montrĂ© sur la figure 4 est la dĂ©finition d’une fonction"max". On peut lire dans le coin en bas Ă  gauche le code Golo accompagnĂ©de la spĂ©cification de la fonction. Dans le coin supĂ©rieur droit apparaissent lesconditions de vĂ©rification gĂ©nĂ©rĂ©es par Why3. Le prouveur Alt-Ergo a Ă©tĂ© lancĂ©pour la fonction et a pu la valider.

Figure 4 – Preuve de la fonction max

24

Page 26: Hardened Golo: Donnez de la confiance en votre code Golo

Les trois exemples suivants sont basĂ©s sur la mĂȘme fonction, effectuant ladivision de deux entiers. La figure 5 montre la fonction effectuant la division sansspĂ©cification. On peut voir que le preuve n’est pas validĂ©e par le prouveur. Celaest dĂ» Ă  la condition de vĂ©rification "not b = 0" de la fonction div, en effet, rienn’empĂȘche d’appeler la fonction avec b=0 ce qui ferait crasher le programme.

Figure 5 – Preuve de la fonction div sans spĂ©cification

Il est attendu que si le programme prends en compte le cas particulier oĂčb=0, alors la preuve doit ĂȘtre valide. On peut vĂ©rifier cela avec la figure 6 : cettefois la vĂ©rification n’échoue pas, le cas ou b=0 Ă©tant traitĂ© sĂ©parĂ©ment.

Dans le cas oĂč l’on souhaite conserver la fonction sans la modifier, il y a lapossibilitĂ© de rajouter une ligne de spĂ©cification pour permettre la vĂ©rification.La figure 7 montre dans un premier temps qu’avec une prĂ©-condition sur b,alors la fonction div passe la vĂ©rification. Cependant, on voit maintenant que lafonction test ne passe pas entiĂšrement la vĂ©rification : la deuxiĂšme prĂ©-conditionn’est pas rĂ©solue. Ce comportement est attendu, la seconde ligne de la fonctionappelant la fonction div avec le paramĂštre b=0, ce qui est dĂ©sormais interditpar la spĂ©cification ajoutĂ©e.

On peut donc voir que spécifier une fonction permet de vérifier que ses appels

25

Page 27: Hardened Golo: Donnez de la confiance en votre code Golo

Figure 6 – Preuve de la fonction div avec if

sont corrects et ne généreront pas de crash.

26

Page 28: Hardened Golo: Donnez de la confiance en votre code Golo

Figure 7 – Preuve de la fonction div avec spĂ©cification

8 BilanPour rĂ©pondre Ă  la problĂ©matique d’ajout de confiance dans du code Golo,

j’ai pris l’approche de traduire le code Golo en WhyML pour l’analyser stati-quement dans l’outil Why3. J’ai dĂ©taillĂ© dans ce rapport mes choix techniques,ainsi que ma contribution, principalement centrĂ©e autour de l’implĂ©mentationd’un traducteur automatique de code, intĂ©grĂ© dans le compilateur Golo.

Parmi les fonctionnalitĂ©s principales, on retrouve la vĂ©rification de l’existencedes fonctions appelĂ©es dans le code, l’ajout de prĂ©-conditions automatiquement(tel que dĂ©nominateur d’une division non-nul), et permis l’ajout de spĂ©cificationde code. Cette implĂ©mentation est une premiĂšre base qui permet d’ĂȘtre Ă©tenduepour supporter plus de fonctionnalitĂ©s dans le futur. Parmi les limitations ac-tuelles, on retrouve notamment : la limitation Ă  un unique module Golo, les aritĂ©de fonctions devant ĂȘtre fixes, la limitation de la spĂ©cification aux fonctions, lasurcharge des opĂ©rateurs, la portĂ©e des variables, ainsi que "result" Ă©tant un nomrĂ©servĂ©.

Une des grandes difficultĂ©s qui doit ĂȘtre rĂ©solue pour pouvoir Ă©tendre la

27

Page 29: Hardened Golo: Donnez de la confiance en votre code Golo

portĂ©e de ce projet rĂ©side dans la gestion du typage : l’implĂ©mentation ac-tuelle ne supporte que les entiers non bornĂ©s. Il est nĂ©cessaire, dans un premiertemps, de dĂ©finir une thĂ©orie pour utiliser des entiers bornĂ©s, puis de supporterd’autres types. Une piste de rĂ©flection pourrait ĂȘtre l’utilisation de structuresgĂ©nĂ©riques WhyML pour dĂ©crire tout Ă©lĂ©ment avec une description du type :genericType{mutable type ; mutable var}. L’utilisation de ce type de structuresnĂ©cessiterait Ă©galement une redĂ©finition des Ă©lĂ©ments de la librairie standardpour redĂ©finir le comportement sur ce nouveau type (notamment les opĂ©ra-teurs).

9 Retour d’expĂ©rienceCe stage m’a permis de dĂ©couvrir plus en dĂ©tail le monde de la recherche,

ainsi que des mĂ©thodologies que je n’avais pas rencontrĂ©es auparavant. La sĂ©pa-ration trĂšs claire durant les premiĂšres semaines entre l’état de l’art et l’implĂ©-mentation m’a permis de bien sĂ©parer la dĂ©finition du problĂšme et les solutionsenvisagĂ©es de l’implĂ©mentation.

N’ayant jamais travaillĂ© sur l’analyse statique auparavant, j’ai appris beau-coup durant ce stage sur ce sujet. J’ai Ă©galement dĂ©couvert le fonctionnementd’un compilateur et d’un gĂ©nĂ©rateur de parseur Ă©crit en Java. Ces diffĂ©rentsaspects techniques nouveaux ont rendu ce stage encore plus intĂ©ressant, car ilsont permis une montĂ©e en compĂ©tences. Ces aspects totalement inconnus furentau dĂ©but la source de nombreuses difficultĂ©s, mais Ă©galement la source d’unegrande motivation une fois les premiĂšres barriĂšres tombĂ©es.

La contribution proposĂ©e est satisfaisante au niveau personnel, avec un Ă©tatde l’art riche et variĂ©, et une implĂ©mentation prĂ©liminaire dont j’estime lesrĂ©sultats encourageants pour le futur.

28

Page 30: Hardened Golo: Donnez de la confiance en votre code Golo

Références[1] Julien Ponge, Frédéric Le Mouël, and Nicolas Stouls. Golo, a dynamic, light

and efficient language for post-invokedynamic jvm. In Proceedings of the2013 International Conference on Principles and Practices of Programmingon the Java Platform : Virtual Machines, Languages, and Tools, PPPJ ’13,pages 153–158, New York, NY, USA, 2013. ACM.

[2] Golo - a lightweight dynamic language for the jvm. http://golo-lang.org/.

[3] François Bobot, Jean-Christophe FilliĂątre, Claude MarchĂ©, and Andrei Pas-kevich. Why3 : Shepherd your herd of provers. In Boogie 2011 : First In-ternational Workshop on Intermediate Verification Languages, pages 53–64,Wroclaw, Poland, 2011.

[4] Claude MarchĂ© and Christine Paulin-Mohring. Reasoning about java pro-grams with aliasing and frame conditions. In Proceedings of the 18thInternational Conference on Theorem Proving in Higher Order Logics,TPHOLs’05, pages 179–194, Berlin, Heidelberg, 2005. Springer-Verlag.

[5] Jean-Christophe Filliñtre and Andrei Paskevich. Why3 – where programsmeet provers. In ESOP’13 22nd European Symposium on Programming,volume 7792, Rome, Italy, March 2013. Springer.

[6] Gary T. Leavens, Albert L. Baker, and Clyde Ruby. Jml : a java modelinglanguage. In In Formal Underpinnings of Java Workshop (at OOPSLA’98),1998.

[7] Nadia Polikarpova and Scott Furia, Carlo A.and West. Runtime Verifica-tion : 4th International Conference, RV 2013, Rennes, France, September24-27, 2013. Proceedings, chapter To Run What No One Has Run Before :Executing an Intermediate Verification Language, pages 251–268. SpringerBerlin Heidelberg, 2013.

[8] François Bobot, Sylvain Conchon, E Contejean, Mohamed Iguernelala, Sté-phane Lescuyer, and Alain Mebsout. The alt-ergo automated theorem pro-ver, 2008. http://alt-ergo.lri.fr/, 2013.

[9] K. Rustan M. Leino and Rosemary Monahan. Reasoning about compre-hensions with first-order smt solvers. In Proceedings of the 2009 ACMSymposium on Applied Computing, SAC ’09, pages 615–622, New York,NY, USA, 2009. ACM.

[10] Carlo A. Furia, Bertrand Meyer, and Sergey Velder. Loop invariants :Analysis, classification, and examples. ACM Comput. Surv., 46(3) :34 :1–34 :51, Jan 2014.

[11] Boogie : A Modular Reusable Verifier for Object-Oriented Programs, 2005.[12] Renaud Pawlak, Carlos Noguera, and Nicolas Petitprez. Spoon : Program

analysis and transformation in java. Research Report RR-5901, Inria, 2006.[13] K. Rustan M. Leino. Logic for Programming, Artificial Intelligence, and

Reasoning : 16th International Conference, LPAR-16, Dakar, Senegal,

29

Page 31: Hardened Golo: Donnez de la confiance en votre code Golo

April 25–May 1, 2010, Revised Selected Papers, chapter Dafny : An Auto-matic Program Verifier for Functional Correctness, pages 348–370. SpringerBerlin Heidelberg, Berlin, Heidelberg, 2010.

[14] Michael Ameri and Carlo A. Furia. Why just boogie ? translating betweenintermediate verification languages. CoRR, abs/1601.00516 :–, 2016.

30