Étude et développement de méthodes formelles permettant d'obtenir du code Scala concurrent certifié correct

par Youssef El Bakouny

Projet de thèse en Informatique

Sous la direction de Tristan Crolard et de Dani Mezher.

Thèses en préparation à Paris, CNAM en cotutelle avec École Supérieure d'Ingénieurs de Beyrouth (ESIB) – Université Saint-Joseph (USJ) , dans le cadre de École doctorale Informatique, télécommunications et électronique (Paris) , en partenariat avec Centre d'études et de recherche en informatique et communications (Paris) (laboratoire) et de Systèmes sûrs - CPR : Conception et Programmation Raisonnées (equipe de recherche) depuis le 01-10-2015 .


  • Résumé

    Présentation et état de l'art Les méthodes dites « formelles » rassemblent un ensemble de techniques et de théories mathématiques permettant de spécifier un logiciel de manière non ambigüe, et de vérifier rigoureusement que ce logiciel est conforme à sa spécification. Nous avons assisté ces dernières années à des avancées significatives dans les techniques de vérification et la démonstration automatique de théorèmes, et ces avancées ont rendu possible la vérification formelle de certains types de logiciels (et où la preuve de correction elle-même peut être obtenue et vérifiée mécaniquement). Les logiciels concernés sont aujourd'hui encore des systèmes dits « critiques », qui sont souvent des systèmes embarqués. Ces systèmes ont la particularité d'être relativement élémentaires sur le plan algorithmique, et sont programmés dans des langages de programmation restreints adaptés à ce type d'application. Cette approche est par exemple exploitée avec succès dans la méthode SPARK Ada [1] (cf. [3] pour une présentation succincte de la version actuelle). La technique de vérification de programmes séquentiels mentionnée ci-dessus (aussi appelée « preuve de programme » et dont les fondements théoriques remontent aux travaux Floyd [6], Hoare [7] et Dijkstra [4]) a le mérite d'être légère à mettre en œuvre : il suffit d'annoter le code source avec des contrats (et des assertions), qui peuvent aussi être utilisés pour une validation par le test [10]. En contrepartie, cette approche reste difficile à exploiter pour un langage de programmation moderne comme Java, qui mélange les styles impératifs et objets, et dont la sémantique est intrinsèquement opérationnelle (ce qui rend les spécifications et les preuves de correction très techniques). Les diverses tentatives de généralisation de ces techniques de preuve de programme à Java ont par conséquent rencontré peu de succès. Pourtant, le domaine d'application des méthodes formelles dépasse clairement celui de systèmes critiques. En effet, de nombreuses applications « sensibles » pourraient bénéficier de techniques similaires (typiquement dans le domaine médical, ou dans le secteur de la banque et de la finance). Il faut donc aborder le problème différemment. Une alternative bien connue pour la vérification de programmes consiste à se placer dès le départ dans un univers plus proche des mathématiques : celui des langages de programmation fonctionnels. Deux méthodes matures existent pour la vérification de programmes fonctionnels : 1. La preuve de programme à partir de contrats, similaire à celle utilisée pour les langages impératifs, mais étendue aux fonctions récursives et types de données inductifs traditionnellement rencontrés dans les programmes fonctionnels. 2. L'extraction de code, garanti correct par construction, à partir d'une preuve développée dans un « assistant de preuve » comme Coq [13] ou Isabelle/HOL [11]. Cette méthode a été appliquée récemment de manière remarquable pour la génération d'un compilateur C certifié correct dans Coq (dans le cadre du projet CompCert [8]). Un langage de programmation fonctionnel nous intéresse en particulier dans le cadre de ce projet : il s'agit du langage Scala [12]. • Scala se distingue des autres langages de programmation orienté objet en fournissant de puissantes fonctionnalités que l'on trouve généralement dans les langages de programmation fonctionnels (comme des fonctions d'ordre supérieur et les types de données abstraits), tout en offrant un système de types statique fort autorisant, par exemple, une forme expressive de types dépendant. • Scala est compilé vers le bytecode de la JVM, ce qui permet une interopérabilité avec Java : il est en particulier possible de développer un projet hybride, mélangeant des sources Java et Scala, et dont la partie sensible serait écrite de préférence en Scala. • Les deux méthodes permettant d'obtenir des programmes fonctionnels certifiés corrects ont été adaptées pour Scala : la plateforme de vérification Leon [2] permet de faire de la preuve de programme Scala à partir de contrats, alors que Isabelle/HOL permet l'extraction de code Scala correct par construction. Les objectifs de cette thèse découlent directement des points mentionnés ci-dessus. Il faut remarquer que ces objectifs mènent naturellement à un programme de recherche qui combine de manière équilibrée des études théoriques (sémantique et logique), des tâches plus techniques (preuve de programmes) et du développement (divers outils). Objectifs de la thèse 1. Étudier les limites actuelles de ces deux méthodes, et comparer l'expressivité des fragments de Scala autorisés par leurs implantations respectives. En particulier, on explorera la possibilité de certifier du code Scala utilisant : • des fonctions d'ordre supérieur ; • des aspects impératifs. 2. Explorer des solutions alternatives pour les deux méthodes. En particulier, on étudiera la possibilité d'extraire du code Scala à partir de Coq (première méthode) et de traduire un programme fonctionnel Scala vers Why3 [5] (seconde méthode). 3. Définir un moyen de combiner les deux méthodes (et les différents outils) au sein d'un même projet, afin d'exploiter pleinement leur complémentarité. Cette complémentarité devra être mises en évidence à travers des études de cas. 4. Étendre l'extraction de code Scala en Isabelle/HOL pour obtenir du code concurrent certifié. On modélisera dans un premier temps la sémantique des futures de Scala (modèle de concurrence hérité de Lisp) dans un cadre purement fonctionnel. Ce modèle simple est déjà suffisamment expressif pour exploiter le parallélisme dans des applications réalistes [9], et permettre de certifier des algorithmes classiques de type map-reduce. Dans un second temps, on étudiera un modèle de concurrence plus expressif (comme le modèle des acteurs dans Scala, hérité de Erlang). Bibliographie [1] J. Barnes. Spark: The Proven Approach to High Integrity Software. Altran Praxis, 2012. [2] R. Blanc, V. Kuncak, E. Kneuss, and P. Suter. An overview of the leon verification system: Verification by translation to recursive functions. In Proceedings of the 4th Workshop on Scala, SCALA '13, pages 1:1–1:10, New York, NY, USA, 2013. ACM. [3] P. Courtieu, M.-V. Aponte, T. Crolard, Z. Zhang, F. Robby, J. Belt, J. Hatcliff, J. Guitton, and T. Jennings. Towards the Formalization of SPARK 2014 Semantics with Explicit Run-time Checks Using Coq. In Proceedings of the 2013 ACM SIGAda Annual Conference on High Integrity Language Technology, HILT '13, pages 21–22, New York, NY, USA, 2013. ACM. [4] E. W. Dijkstra. A simple axiomatic basis for programming language constructs. Technical report, Technological Univ., Eindhoven, May 1973. [5] J.-C. Filliâtre and A. Paskevich. Why3 - Where Programs Meet Provers. In Programming Languages and Systems - 22nd European Symposium on Programming, ESOP 2013, Held as Part of the European Joint Conferences on Theory and Practice of Software, ETAPS 2013, Rome, Italy, March 16-24, 2013. Proceedings, pages 125–128, 2013. [6] R. W. Floyd. Assigning meanings to programs. Mathematical Aspects of Computer Science, 19(19-32):1, 1967. [7] C. A. R. Hoare. An axiomatic basis for computer programming. Commun. ACM, 12(10):576–580, 1969. [8] X. Leroy. Mechanized semantics for compiler verification. In Ranjit Jhala and Atsushi Igarashi, editors, Programming Languages and Systems, 10th Asian Symposium, APLAS 2012, volume 7705 of Lecture Notes in Computer Science, pages 386–388. Springer, 2012. Abstract of invited talk. [9] D. Matthews and M. Wenzel. Efficient parallel programming in poly/ml and isabelle/ml. In Proceedings of the 5th ACM SIGPLAN Workshop on Declarative Aspects of Multicore Programming, DAMP '10, pages 53–62, New York, NY, USA, 2010. ACM. [10] B. Meyer. Object-oriented Software Construction. Prentice Hall, New York, N.Y., 1988. [11] T. Nipkow, L. C. Paulson, and M. Wenzel. Isabelle/HOL: a proof assistant for higher-order logic. Springer, 2002. [12] M. Odersky and T. Rompf. Unifying functional and object-oriented programming with scala. Commun. ACM, 57(4):76–86, 2014. [13] The Coq development team. The Coq proof assistant reference manual. TypiCal Project, 2014. Version 8.4.

  • Titre traduit

    Study and development of formal methods yielding concurrent Scala code which is certified to be correct


  • Résumé

    Presentation and state of the art The so-called “formal” methods are gathering of a set of techniques and mathematical theories allowing both the specification of a software system in an unambiguous manner, and the rigorous verification of the conformity of this software system with regards to its specification. We have witnessed, in recent years, significant advances in verification techniques and automated theorem proving. These advances have enabled the formal verification of certain types of software (where the proof of correctness can itself be obtained and checked mechanically). The concerned software systems are, at the time of this writing, still limited to the so-called “critical” systems, which are often embedded systems. These systems have the peculiarity of being relatively basic on the algorithmic level, and are programmed in restricted programming languages suitable for this type of application. This approach is, for example, successfully exploited in the SPARK Ada [1] method (cf. [3] for a succinct presentation of the current version). The above-mentioned sequential program verification technique (also called “program proving” and whose theoretical foundations date back to the works of Floyd [6], Hoare [7] and Dijkstra [4]) has the merit of being light to put in place: it merely requires the source code to be annotated with contracts (and assertions), which could also be used to conduct test validation [10]. On the other hand, this approach remains hardly exploitable for a modern programming language such as Java, which mixes imperative and object-oriented styles, and whose semantics are inherently operational (making specifications and proofs of correctness quite technical). The various attempts to generalize these program proof techniques to the Java programming language have, therefore, been met with little success. Yet the scope of formal methods clearly exceeds that of critical systems. In fact, many “sensitive” applications could benefit from similar techniques (typically in the medical field, or in the financial and banking sector). We must, therefore, approach the problem differently. A well-known program verification alternative consists in placing one's self, from the beginning, in a universe closer to mathematics: that of functional programming languages. Two mature methods exist for functional program verification: 1. The proof of programs through contracts, similar to the one used for imperative languages, but extended to the recursive functions and inductive data structures that are traditionally found in functional programs. 2. The extraction of code, guaranteed to be correct-by-construction, from a proof developed in a “proof assistant” such as Coq [13] or Isabelle / HOL [11]. This method has recently been applied, with remarkable success, for the generation of a C compiler that is certified, in Coq, to be correct-by-construction (cf. the CompCert [8] project). A specific functional programming language is of particular interest to us in this project: the Scala language. [12] • Scala distinguishes itself from other object-oriented programming languages by providing powerful functionalities that are typically found in functional programming languages (such as higher-order functions and abstract data types), while, at the same time, offering a strong static type system allowing, for example, an expressive form of dependent types. • Scala is compiled to JVM bytecode, which makes it interoperable with Java: it is, therefore, possible to develop a hybrid project mixing both Java and Scala sources, where the sensitive parts of the project would be preferably written in Scala. • The two methods resulting in functional programs that are certified to be correct have been adapted to Scala: the Leon [2] verification platform can prove Scala programs through contracts, while Isabelle / HOL allows the extraction of Scala code that is correct-by-construction. The objectives of this thesis directly result from the above-mentioned points. It should be noted that these objectives naturally lead to a research program that equally combines theoretical studies (semantic and logical), other more technical tasks (program proving) and development (various tools). Objectives of the thesis 1. Study the current limitations of these two methods and compare the expressiveness of Scala fragments authorized by their respective implementations. In particular, we will explore the possibility of certifying Scala code that uses: • Higher-order functions; • Imperative aspects. 2. Explore alternative solutions for both methods. In particular, we will explore the possibility of extracting Scala code from Coq (first method) and translating a Scala functional program to Why3 [5] (second method). 3. Define a way to combine the two methods (and their respective tools) within the same project, in order to fully exploit their complementarity. This complementarity should be exhibited through case studies. 4. Extend the Scala code extraction in Isabelle / HOL to generate certified concurrent code. As a first step, we will model the semantics of Scala Futures (a concurrency model inherited from Lisp) in a purely functional setting. This simple model is already sufficiently expressive to exploit parallelism in realistic applications [9], and to allow the certification of classical algorithms of type map-reduce. As a second step, we will study a more expressive concurrency model (such as the model of actors in Scala, inherited from Erlang). Bibliography [1] J. Barnes. Spark: The Proven Approach to High Integrity Software. Altran Praxis, 2012. [2] R. Blanc, V. Kuncak, E. Kneuss, and P. Suter. An overview of the leon verification system: Verification by translation to recursive functions. In Proceedings of the 4th Workshop on Scala, SCALA '13, pages 1:1–1:10, New York, NY, USA, 2013. ACM. [3] P. Courtieu, M.-V. Aponte, T. Crolard, Z. Zhang, F. Robby, J. Belt, J. Hatcliff, J. Guitton, and T. Jennings. Towards the Formalization of SPARK 2014 Semantics with Explicit Run-time Checks Using Coq. In Proceedings of the 2013 ACM SIGAda Annual Conference on High Integrity Language Technology, HILT '13, pages 21–22, New York, NY, USA, 2013. ACM. [4] E. W. Dijkstra. A simple axiomatic basis for programming language constructs. Technical report, Technological Univ., Eindhoven, May 1973. [5] J.-C. Filliâtre and A. Paskevich. Why3 - Where Programs Meet Provers. In Programming Languages and Systems - 22nd European Symposium on Programming, ESOP 2013, Held as Part of the European Joint Conferences on Theory and Practice of Software, ETAPS 2013, Rome, Italy, March 16-24, 2013. Proceedings, pages 125–128, 2013. [6] R. W. Floyd. Assigning meanings to programs. Mathematical Aspects of Computer Science, 19(19-32):1, 1967. [7] C. A. R. Hoare. An axiomatic basis for computer programming. Commun. ACM, 12(10):576–580, 1969. [8] X. Leroy. Mechanized semantics for compiler verification. In Ranjit Jhala and Atsushi Igarashi, editors, Programming Languages and Systems, 10th Asian Symposium, APLAS 2012, volume 7705 of Lecture Notes in Computer Science, pages 386–388. Springer, 2012. Abstract of invited talk. [9] D. Matthews and M. Wenzel. Efficient parallel programming in poly/ml and isabelle/ml. In Proceedings of the 5th ACM SIGPLAN Workshop on Declarative Aspects of Multicore Programming, DAMP '10, pages 53–62, New York, NY, USA, 2010. ACM. [10] B. Meyer. Object-oriented Software Construction. Prentice Hall, New York, N.Y., 1988. [11] T. Nipkow, L. C. Paulson, and M. Wenzel. Isabelle/HOL: a proof assistant for higher-order logic. Springer, 2002. [12] M. Odersky and T. Rompf. Unifying functional and object-oriented programming with scala. Commun. ACM, 57(4):76–86, 2014. [13] The Coq development team. The Coq proof assistant reference manual. TypiCal Project, 2014. Version 8.4.