A Logic Meta Programming Foundation for Example-Driven Pattern Detection in Object-Oriented Programs
Total Page:16
File Type:pdf, Size:1020Kb
FACULTEIT WETENSCHAPPEN Vakgroep Computerwetenschappen Software Languages Lab A Logic Meta Programming Foundation for Example-Driven Pattern Detection in Object-Oriented Programs Proefschrift ingediend met het oog op het behalen van de graad van Doctor in de Wetenschappen Coen De Roover Academiejaar 2008 - 2009 Promotoren: Prof. Dr. Wolfgang De Meuter en Dr. Johan Brichau ABSTRACT The growing number of tools for detecting user-specified software patterns is testa- ment to their valuable applications throughout the development process. In these ap- plications, user-specified software patterns describe code that exhibits characteristics of interest. For instance, violations of the protocol an API expects to be adhered to. Logic formulas can be used as expressive and descriptive pattern specifications. This merely requires reifying the program under investigation such that variables can range over its elements. Executing a proof procedure will establish whether program elements exhibit the characteristics specified in a formula. However, we have observed that such formulas become convoluted and operational in nature when developers attempt to ensure all instances of a pattern are recalled. As the behavioral characteristics of a pattern can be implemented in different ways, the corresponding formula either has to enumerate each implementation variant or describe the machine-verifiable behavior shared by these variants. The former for- mulas are relatively descriptive, but only recall the implementation variants that are enumerated. The latter formulas recall all implementations of the specified behavior, but do so by quantifying over information about the program’s behavior. This exposes developers to the intricate details of the program analyses that compute this informa- tion. We have reconciled both approaches by embedding source code excerpts in lo- gic formulas. These excerpts exemplify the prototypical implementation of a pattern’s characteristics —thus ensuring the resulting specifications are descriptive. They are specified in the concrete syntax of the base program augmented with logic variables. To ensure that all implementation variants are recalled, these excerpts are matched against behavioral program information according to multiple matching strategies that vary in leniency. Each match is quantified by the extent to which it exhibits the speci- fied characteristics. The smaller this extent, the more likely the match is a false posi- tive. This establishes a ranking which facilitates assessing a large amount of matches. A logic of quantified truth provides the theoretical foundation for this ranking. Unique to our matching process is that it incorporates whole-program analyses in its comparison of individual program elements. A semantic analysis ensures cor- rectness. To compare an unqualified and fully qualified type, for instance, a semantic analysis takes the import declarations into account of the compilation units in which they reside. A points-to analysis increases the amount of implementation variants that are recalled. When expressions are compared, for instance, syntactic deviations are allowed as long as they may evaluate to the same object at run-time. The resulting example-driven approach to pattern detection recalls the implicit im- plementation variants (i.e. those that are implied by the semantics of the programming language) of a machine-verifiable characteristic specified as a code excerpt that exem- plifies its prototypical implementation. iii SAMENVATTING Het groeiend aantal tools voor het detecteren van door ontwikkelaars gespecifi- ceerde software-patronen getuigt van de waardevolle toepassingen van patroondetec- tie doorheen het ontwikkelingsproces. In deze toepassingen beschrijft een software- patroon telkens code die aan bepaalde eigenschappen voldoet. Een patroon kan bij- voorbeeld schendingen beschrijven van het protocol dat gevolgd moet worden bij het aanroepen van een API. Logische formules lenen zich tot descriptieve specificaties van zulke patronen. Hiertoe is slechts een reïficatie van het programma vereist zodat formules over de elementen van het programma kunnen kwantificeren. Het uitvoeren van een bewijs- procedure bepaalt dan of elementen van het programma voldoen aan de geformu- leerde eigenschappen. We hebben echter vastgesteld dat zulke formules eerder ope- rationeel en verre van descriptief dreigen te worden wanneer ontwikkelaars ervoor trachten te zorgen dat alle instanties van het patroon gedetecteerd worden. Aangezien de eigenschappen van een patroon op verschillende manieren ge- ïmplementeerd kunnen worden, moet de corresponderende formule ofwel elke im- plementatievariant opsommen ofwel het gemeenschappelijke gedrag van deze vari- anten beschrijven. De eerstgenoemde formules zijn relatief descriptief, maar kunnen slechts de opgesomde implementatievarianten detecteren. De laatstgenoemde for- mules kunnen verschillende implementaties van het gespecificeerde gedrag detecte- ren, maar moeten hiervoor kwantificeren over informatie die het eigenlijk gedrag van het programma beschrijft. Hierdoor worden ontwikkelaars blootgesteld aan verre van eenvoudige programma-analyses die deze informatie berekenen. Door broncodemallen te integreren in logische formules hebben we beide opties met elkaar verzoend. Deze van logische variabelen voorziene fragmenten broncode fungeren als een voorbeeld van de prototypische implementatie van de eigenschap- pen van een patroon. Als voorbeelden van een implementatie waarborgen zij de de- scriptiviteit van de resulterende patroonspecificaties. Opdat implementatievarianten gedetecteerd zouden worden, vergelijken we zulke broncodemallen met informatie over het gedrag van het programma volgens meerdere strategieën die verschillen in striktheid. Een zogenaamde match bestaat uit bindingen voor de logische variabelen die de broncodemal vervolledigen. Voor elke match kwantificeren we de mate waarin deze aan de gespecificeerde eigenschappen voldoet. Geringe mates zijn indicatoren van valse positieven. De op deze manier verwezenlijkte rangschikking vergemakkelijkt het inspecteren van een groot aantal matchen. Een logica van gekwantificeerde waar- heid ondersteunt deze rangschikking theoretisch. Uniek aan bovenstaand vergelijkingsproces is dat analyses die informatie over het gedrag van het volledige programma berekenen, geconsulteerd worden bij het ver- gelijken van individuele programma-elementen. De correctheid van matches wordt gevrijwaard door een semantische analyse. Bij het vergelijken van een ongekwalifi- iv ceerd type met een volledig gekwalificeerd type, houdt de semantische analyse bij- voorbeeld rekening met de import-declaraties van de compilatie-eenheden waarin beiden zich bevinden. Een points-to analyse verhoogt het aantal implementatie- varianten dat gedetecteerd wordt. Bij het vergelijken van expressies zijn syntactische afwijkingen bijvoorbeeld toegestaan, op voorwaarde dat de expressies kunnen evalu- eren naar eenzelfde object tijdens een uitvoering van het programma. De resulterende voorbeeldgedreven patroondetectietechniek detecteert impliciete implementatievarianten (deze die volgen uit de semantiek van de programmeertaal) van een patrooneigenschap die gespecificeerd is als een fragment broncode dat fun- geert als voorbeeld van de prototypische implementatie van de eigenschap. v ACKNOWLEDGEMENTS I am greatly indebted to my promotor Prof. Wolfgang De Meuter (Vrije Universiteit Brussel) and co-promotor Dr. Johan Brichau (Université catholique de Louvain). Johan has been my partner in crime from the moment I was ready to dive into his implementation of the SOUL interpreter. I have truly enjoyed our joint work on logic meta programming and I am looking forward to continuing this fruitful col- laboration. Despite my stubbornness, Wolfgang never ceased to offer indispens- able advise —from the years that preceded my first keystrokes in “thesis.tex” to mere hours before I was presenting “private_defense.keynote”. Over the years, his interventions have been crucial to my evolution from a student to a researcher. It is impossible to thank both Wolfgang and Johan properly for their tremendous support, patience and the countless hours they have spent proofreading each chap- ter. I have not only come to appreciate them as outstanding advisors, but also as friends. I sincerely thank the members of my jury for their insightful comments and the significant time they have invested: Prof. Michael W. Godfrey (University of Water- loo), Prof. Ralf Lämmel (Universität Koblenz-Landau), Prof. Viviane Jonckers (Vrije Universiteit Brussel), Prof. Dirk Vermeir (Vrije Universiteit Brussel) and Prof. Theo D’Hondt (Vrije Universiteit Brussel). Next time, I will try to be more concise. During my years as an undergraduate student, I had the pleasure of experiencing the inter- nal jury members as gifted teachers who sparked my interests in software engineer- ing, logic programming and language engineering respectively —the confluence of which my research is situated in. I wish to extend my sincerest gratitude to Prof. Theo D’Hondt in particular, for welcoming me in the intellectually stimulating environment he has founded and fostered in his own intriguing style. Working at his laboratory has been an unpar- alleled and extremely gratifying experience. The amounts of trust and freedom to explore that are granted by Theo makes teaching practical sessions for his classes a joy. Moreover, I can only dream of ever mastering all of the clever insights that are delightfully tucked away in the corners