Adding Crucial Features to a Typestate-Oriented Language
Total Page:16
File Type:pdf, Size:1020Kb
João Daniel da Luz Mota Bachelor in Computer Science and Engineering Coping with the reality: adding crucial features to a typestate-oriented language Dissertation submitted in partial fulfillment of the requirements for the degree of Master of Science in Computer Science and Engineering Adviser: António Maria Lobo César Alarcão Ravara, Associate Professor, NOVA School of Science and Technology Co-adviser: Marco Giunti, Researcher, NOVA School of Science and Technology Examination Committee Chair: Hervé Miguel Cordeiro Paulino, Associate Professor, NOVA School of Science and Technology Rapporteur: Ornela Dardha, Lecturer, School of Computing Science, University of Glasgow Members: António Maria Lobo César Alarcão Ravara Marco Giunti February, 2021 Coping with the reality: adding crucial features to a typestate-oriented lan- guage Copyright © João Daniel da Luz Mota, NOVA School of Science and Technology, NOVA University Lisbon. The NOVA School of Science and Technology and the NOVA University Lisbon have the right, perpetual and without geographical boundaries, to file and publish this dissertation through printed copies reproduced on paper or on digital form, or by any other means known or that may be invented, and to disseminate through scientific repositories and admit its copying and distribution for non-commercial, educational or research purposes, as long as credit is given to the author and editor. Acknowledgements Throughout the writing of this thesis I have received a great deal of support and assis- tance. I would first like to thank my adviser, Professor António Ravara, and co-adviser, Re- searcher Marco Giunti, for the guidance and direction provided. Your feedback was crucial and allowed me to organize my work and write this thesis. I would like to acknowledge all the professors who during these years have given me the skills and knowledge necessary to push me to become a good engineer in the future. I would also like to thank my colleagues, which during these years, through the exchanging of ideas, have helped me grow. Finally, I could not have completed this work without the support of my parents, Cidália and Mário, who were very kind and patient with me throughout these years. v “Unless the Lord builds the house, those who build it labor in vain.” (Psalm 127:1; ESV) Abstract Detecting programming errors and vulnerabilities in software is increasingly impor- tant, and building tools that help with this task is an area of investigation, crucial for the industry these days. When programming in an object-oriented language, one naturally defines stateful objects that are non-uniform, i.e., their methods’ availability depends on their internal state. One might represent their intended usage protocol with an au- tomaton or a state machine. Behavioral types allow to statically check if all the code of a program respects the usage protocol of each object. In this thesis we present a tool that extends Java with typestate definitions. These typestates are associated with Java classes and define the behavior of instances of those classes, specifying the sequences of method calls allowed. This tool checks statically that method calls happen in order, following the specified behavior. The tool was implemented in Kotlin as a plugin for the Checker Framework. It is a new implementation of the Mungo tool and supports prevention of null pointer errors, state transitions depending on return values, assurance of protocol completion, drop- pable states, and association of protocols with classes from the standard Java library or from third-party libraries. Additionally, the tool integrates behavioral types with ac- cess permissions, allowing objects to be shared in a controlled way using a language of assertions. This language of assertions supports concepts like packing and unpacking, including unpacking of aliases objects, and transferring of permissions between aliases. To relieve the programmer from manually writing all the necessary assertions, the tool implements an inference algorithm which analyzes the code statically and, given the uses of objects, constructs all the required assertions. Keywords: Behavioral types, object-oriented programming, typestates, session types, access permissions, inference ix Resumo A deteção de erros de programação e vulnerabilidades no software é cada vez mais importante, e a criação de ferramentas que ajudem nesta tarefa é uma área de investi- gação crucial para a indústria atualmente. Ao programar numa linguagem orientada a objetos, definem-se naturalmente objetos com estado que não são uniformes, ou seja, a disponibilidade dos seus métodos depende do seu estado interno. Pode-se representar o protocolo de uso pretendido com um autómato ou uma máquina de estados. Os tipos comportamentais permitem verificar estaticamente se todo o código de um programa respeita o protocolo de uso de cada objeto. Nesta tese apresentamos uma ferramenta que estende o Java com definições de type- states. Esses estão associados às classes Java e definem o comportamento das instâncias dessas classes, especificando as sequências de chamadas de métodos permitidas. Esta fer- ramenta verifica estaticamente se as chamadas de métodos ocorrem pela ordem correta, seguindo o comportamento especificado. A ferramenta foi implementada em Kotlin como um plugin para o Checker Framework. É uma implementação nova da ferramenta Mungo e suporta a prevenção de erros de ponteiro nulo, transições de estado dependendo de valores de retorno, asseguração da conclusão dos protocolos, objetos que podem ser «largados», e a associação de protocolos com classes da biblioteca padrão do Java ou de terceiros. Além disso, esta integra tipos comportamentais com permissões de acesso, permitindo que objetos possam ser parti- lhados por meio de uma linguagem de asserções. Esta linguagem de asserções oferece suporte para conceitos como packing e unpacking, incluindo unpacking de objetos parti- lhados, e transferência de permissões entre variáveis que apontam para o mesmo objeto. Para aliviar o programador de escrever manualmente todas as asserções necessárias, a ferramenta implementa um algoritmo de inferência que analisa o código estaticamente e, consoante os usos dos objetos, constrói todas as asserções necessárias. Palavras-chave: Tipos comportamentais, programação orientada a objetos, typestates, session types, permissões de acesso, inferência xi Contents List of Figures xvii List of Tables xix Glossary xxi 1 Introduction1 1.1 Context...................................... 1 1.2 Problem...................................... 1 1.3 Contributions .................................. 2 1.4 Thesis outline .................................. 3 2 Theoretical Work on Behavioral Types5 2.1 Typestates .................................... 5 2.2 Session types................................... 6 2.3 Typestates/Session types/Usage types .................... 6 2.4 Motivating example: Checker Framework .................. 7 2.5 Conclusion.................................... 8 3 Practical work on Behavioral Types9 3.1 Typestate-oriented approaches......................... 9 3.1.1 Plaid ................................... 9 3.1.2 Fugue................................... 10 3.1.3 Contractor.NET............................. 12 3.2 Usage types approaches............................. 13 3.2.1 Bica.................................... 13 3.2.2 Mool ................................... 14 3.2.3 Mungo.................................. 16 3.3 Summary..................................... 18 4 Typestate-oriented tool: version 1 19 4.1 Design choices.................................. 19 4.1.1 Checker Framework .......................... 20 4.1.2 Kotlin................................... 20 xiii CONTENTS 4.2 Type-checker features.............................. 22 4.2.1 Protocols................................. 22 4.2.2 State refinement............................. 24 4.2.3 Nullness checking............................ 26 4.2.4 Protocol completion .......................... 26 4.2.5 Droppable states ............................ 28 4.2.6 Protocols for classes of libraries.................... 29 4.3 Type-checker implementation......................... 30 4.3.1 Type system............................... 30 4.3.2 Architecture............................... 34 4.3.3 Class analysis .............................. 36 4.3.4 Inference and checking......................... 37 4.4 Comparison with Mungo............................ 49 4.4.1 Basic checking.............................. 50 4.4.2 Decisions on boolean values...................... 52 4.4.3 Nullness checking............................ 54 4.4.4 Linearity checking ........................... 56 4.4.5 Force protocol completion....................... 61 4.4.6 Class analysis .............................. 64 4.4.7 State refinement via annotations ................... 69 4.4.8 Droppable transition.......................... 71 4.4.9 Protocols for classes of libraries.................... 72 4.4.10 Improved flow analysis......................... 73 4.4.11 Decisions based on equality checks in conditions.......... 76 4.5 Conclusion.................................... 77 5 Theoretical work on Access Permissions 79 5.1 Owicki-Gries method and Rely-Guarantee.................. 79 5.2 Separation Logic................................. 80 5.3 Access permissions ............................... 80 5.3.1 Fractional permissions......................... 81 5.3.2 Counting permissions ......................... 81 5.3.3 Symbolic permissions.......................... 81 5.4