Grigore Rosu University of Illinois at Urbana-Champaign, USA

Slides:



Advertisements
Similar presentations
An Abstract Interpretation Framework for Refactoring P. Cousot, NYU, ENS, CNRS, INRIA R. Cousot, ENS, CNRS, INRIA F. Logozzo, M. Barnett, Microsoft Research.
Advertisements

Semantics Static semantics Dynamic semantics attribute grammars
ICE1341 Programming Languages Spring 2005 Lecture #6 Lecture #6 In-Young Ko iko.AT. icu.ac.kr iko.AT. icu.ac.kr Information and Communications University.
Introducing Formal Methods, Module 1, Version 1.1, Oct., Formal Specification and Analytical Verification L 5.
Hoare’s Correctness Triplets Dijkstra’s Predicate Transformers
1 How to transform an analyzer into a verifier. 2 OUTLINE OF THE LECTURE a verification technique which combines abstract interpretation and Park’s fixpoint.
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 11.
1 Mechanical Verification of Timed Automata Myla Archer and Constance Heitmeyer Presented by Rasa Bonyadlou 24 October 2002.
ISBN Chapter 3 Describing Syntax and Semantics.
CS 330 Programming Languages 09 / 19 / 2006 Instructor: Michael Eckmann.
1 Semantic Description of Programming languages. 2 Static versus Dynamic Semantics n Static Semantics represents legal forms of programs that cannot be.
CS 355 – Programming Languages
1 Formal Methods in SE Qaisar Javaid Assistant Professor Lecture 05.
1 Basic abstract interpretation theory. 2 The general idea §a semantics l any definition style, from a denotational definition to a detailed interpreter.
CS 290C: Formal Models for Web Software Lecture 10: Language Based Modeling and Analysis of Navigation Errors Instructor: Tevfik Bultan.
CS 330 Programming Languages 09 / 18 / 2007 Instructor: Michael Eckmann.
Programming Language Semantics Mooly SagivEran Yahav Schrirber 317Open space html://
Some administrative stuff Class mailing list: –send to with the command “subscribe”
Semantics with Applications Mooly Sagiv Schrirber html:// Textbooks:Winskel The.
CS 330 Programming Languages 09 / 16 / 2008 Instructor: Michael Eckmann.
Describing Syntax and Semantics
Formal Methods 1. Software Engineering and Formal Methods  Every software engineering methodology is based on a recommended development process  proceeding.
Matching Logic Grigore Rosu University of Illinois at Urbana-Champaign, USA 1.
Reading and Writing Mathematical Proofs
ISBN Chapter 3 Describing Semantics -Attribute Grammars -Dynamic Semantics.
Slide 1 Propositional Definite Clause Logic: Syntax, Semantics and Bottom-up Proofs Jim Little UBC CS 322 – CSP October 20, 2014.
Checking Reachability using Matching Logic Grigore Rosu and Andrei Stefanescu University of Illinois, USA.
3.2 Semantics. 2 Semantics Attribute Grammars The Meanings of Programs: Semantics Sebesta Chapter 3.
Chapter 3 Part II Describing Syntax and Semantics.
Programming Languages and Design Lecture 3 Semantic Specifications of Programming Languages Instructor: Li Ma Department of Computer Science Texas Southern.
Semantics In Text: Chapter 3.
From Hoare Logic to Matching Logic Reachability Grigore Rosu and Andrei Stefanescu University of Illinois, USA.
CMSC 330: Organization of Programming Languages Operational Semantics a.k.a. “WTF is Project 4, Part 3?”
All-Path Reachability Logic Andrei Stefanescu 1, Stefan Ciobaca 2, Radu Mereuta 1,2, Brandon Moore 1, Traian Serbanuta 3, Grigore Rosu 1 1 University of.
Static Techniques for V&V. Hierarchy of V&V techniques Static Analysis V&V Dynamic Techniques Model Checking Simulation Symbolic Execution Testing Informal.
Specify and Verify Your Language using K Grigore Rosu University of Illinois at Urbana-Champaign Joint project between the FSL group at UIUC (USA) and.
CMSC 330: Organization of Programming Languages Operational Semantics.
CSC3315 (Spring 2009)1 CSC 3315 Languages & Compilers Hamid Harroud School of Science and Engineering, Akhawayn University
Prof. Necula CS 164 Lecture 171 Operational Semantics of Cool ICOM 4029 Lecture 10.
Operational Semantics Mooly Sagiv Tel Aviv University Sunday Scrieber 8 Monday Schrieber.
Operational Semantics Mooly Sagiv Reference: Semantics with Applications Chapter 2 H. Nielson and F. Nielson
K Framework Grigore Rosu University of Illinois at Urbana-Champaign, USA Traian-Florin Serbanuta Alexandru Ioan-Cuza University, Iasi, Romania Joint work.
Certifying and Synthesizing Membership Equational Proofs Patrick Lincoln (SRI) joint work with Steven Eker (SRI), Jose Meseguer (Urbana) and Grigore Rosu.
Functional Programming
CS598 - Runtime verification
The Relationship Between Separation Logic and Implicit Dynamic Frames
CS510 Compiler Lecture 4.
Matching Logic An Alternative to Hoare/Floyd Logic
C++ coding standard suggestion… Separate reasoning from action, in every block. Hi, this talk is to suggest a rule (or guideline) to simplify C++ code.
CS 326 Programming Languages, Concepts and Implementation
A lightening tour in 45 minutes
Towards trustworthy refactoring in Erlang
Business Process Measures
(One-Path) Reachability Logic
runtime verification Brief Overview Grigore Rosu
Symbolic Implementation of the Best Transformer
Functions Inputs Output
Matching Logic - A New Program Verification Approach -
Lecture 5 Floyd-Hoare Style Verification
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
Java Programming Loops
Generating Optimal Linear Temporal Logic Monitors by Coinduction
A Language-Independent Approach To Smart Contract Verification
Functional Program Verification
Towards a Unified Theory of Operational and Axiomatic Semantics
Java Programming Loops
Language-Independent Verification Framework
This Lecture Substitution model
A Language-Independent Approach To Smart Contract Verification
Programming Languages and Compilers (CS 421)
Presentation transcript:

Grigore Rosu University of Illinois at Urbana-Champaign, USA From Rewriting Logic, to Programming Language Semantics, to Program Verification Grigore Rosu University of Illinois at Urbana-Champaign, USA

How it all started 1996: Started PhD with Joseph Goguen Discovered Maude as “fast OBJ”, then rewriting logic 2000: Started at NASA Ames Started meeting with Jose regularly at SRI 2001: Jose moved to UIUC Invited me to visit, then encouraged me to apply 2002: Started at UIUC 2003: Jose (and Gul Agha) asked me to teach PL 2005: Rewriting Logic Semantics Project Countless hours of discussions; how far can it go?

Rewriting Logic Semantics Vision Deductive program verifier Parser Interpreter Formal Language Definition (Syntax and Semantics) Model checker Symbolic execution (semantic) Debugger K is a language design framework and suite of tools. Its vision is to allow and encourage the language designers to formally define their languages once and for all, using an intuitive and attractive notation, and then obtain essentially for free implementations as well as analysis tools for the defined languages. This is a long-standing dream of the programming language community. Our objective in the K project is to develop the foundations, techniques, and tools to make this dream a reality. Compiler

The Adventure Began I was sold, this was too beautiful to pass Question was: does it really work? We tried various semantic styles Small-step and big-step SOS Reduction semantics with evaluation contexts Chemical abstract machine Continuation-based style, denotational But each of the above had limitations Especially related to modularity and verification K framework was engineered to avoid limitations Initially implemented by translation to Maude

K Team http://kframework.org UIUC, USA Romania Former members Grigore Rosu (started K in 2003) Brandon Moore Daejun Park Lucas Pena Cosmin Radoi Yuwen Shijiao Andrei Stefanescu Former members Kyle Blocher, Thomas Bogue, Peter Dinges, Chucky Ellison, Cansu Erdogan, Dwight Guth, Mike Ilseman, David Lazar, Patrick Meredith, Erick Mikida, Traian Serbanuta Runtime Verification, Inc., USA Dwight Guth Manasvi Saxena Romania Dorel Lucanu Traian Florin Serbanuta Andrei Arusoae Stefan Ciobaca Radu Mereuta Former Members Irina Asavoae, Mihai Asavoae, Denis Bogdanas, Gheorghe Grigoras, Emilian Necula, Raluca Necula Traian Serbanuta is currently the K tool development lead.

K Approach Deductive program verifier Test-case generation Parser Interpreter Formal Language Definition (Syntax and Semantics) Model checker Symbolic execution (semantic) Debugger Recall our overall approach: one formal definition of the language given once and for all, and then the various tools derived from the formal definition. Compiler

Complete K Definition of KernelC Here is a complete definition of a fragment of C, called KernelC, as generated by the K tool. The left column defines its formal syntax and the other two its formal semantics. I will next zoom through this definition and highlight some of the K tool’s features.

Complete K Definition of KernelC Syntax declared using annotated BNF … Syntax is declared using the conventional BNF notation, annotated with K attributes (in blue). For example, assignment is an expression construct taking two expression arguments (the left one can be a variable x, a pointer *x, etc.; we only discuss the former case here). The “strict(2)” annotation states that assignment is strict in the second argument, that is, that argument needs to be evaluated first. The semantic rule of assignment, which we discuss shortly, then can assume that the second argument is already a value.

Complete K Definition of KernelC Configuration given as a nested cell structure. Leaves can be sets, multisets, lists, maps, or syntax K makes heavy use of configurations, which in the tool can be defined and initialized in a user friendly and colorful way. A configuration can be regarded as a snapshot of the program execution: it includes the remaining program, together with all the necessary semantic information to execute it. K configurations are organized as nested cell structures, whose leaves hold basic data organized in lists, maps, sets, etc. Cells can be referred to by their name; their order is irrelevant. In KernelC, the k cell holds the remaining code, funs the set of functions, env the current environment, mem the current heap, fstack the current function stack, in and out the current input/output buffers, ptr the current malloc/free pointer map, and so on.

Complete K Definition of KernelC Semantic rules given contextually rule <k> X = V => V …</k> <env>… X |-> (_ => V) …</env> Once the syntax and configuration are defined, we can start adding semantic rules. K rules are contextual: they mention a configuration context in which they apply, together with local changes they make to that context. To enhance the modularity of your language definition, you typically aim at only mentioning the absolutely necessary context in your rules; the remaining details are filled in automatically by the tool. For example, here is the K rule for assignment, both in graphical and in ASCII formats; we only discuss the graphical notation here. Recall that assignment was strict(2), so we can assume that its second argument is a value, say V. The context of this rule involves two cells, the k cell which holds the current code and the env cell which holds the current environment. Moreover, from each cell, we only need certain pieces of information: from the k cell we only need the first task, which is the assignment X=V, and from the env cell we only need the binding X |-> _. The underscore stands for an anonymous variable, the intuition here being that that value is discarded anyway, so there is no need to bother naming it. The unnecessary parts of the cells, which we call frames, are metaphorically “torn away” and ignored, as suggested by the tears. Then, once the local context is established, we identify the parts of the context which need to change, underlying them, and then provide the changes under the lines. In our case, we rewrite both the assignment expression and the value of X in the environment to the assigned value V. Everything else stays unchanged. The concurrent semantics of K regards each rule as a transaction: all changes in a rule happen concurrently; moreover, rules themselves apply concurrently, provided their changes do not overlap.

K Scales Several large languages were recently defined in K: Java 1.4: by Bogdanas etal [POPL’15] 800+ program test suite that covers the semantics JavaScript ES5: by Park etal [PLDI’15] Passes existing conformance test suite (2872 pgms) Found (confirmed) bugs in Chrome, IE, Firefox, Safari C11: Ellison etal [POPL’12, PLDI’15] All 77 different types of undefined behavior Commercialized by startup (Runtime Verification, Inc.) … K scales! Besides a series of smaller and paradigmatic languages that are used for teaching purposes, there are several large and real languages that have been given semantics in K, such as: Java has been defined by Bogdanas; Javascript by Park and Stefanescu; C by Ellison etal; just to mention a few. Many other large K semantics are under development.

K Configuration and Definition of C Heap To give an idea what it takes to define a large language, here is, for example, the configuration of C. It has more than 70 cells! The heap, which is the subject of so many debates in program verification, is just one of them. 120 Cells! … plus ~2000 rules …

K Semantics are testable! Parser Interpreter Formal Language Definition (Syntax and Semantics) (semantic) Debugger

Testing the K definition of C Tested on thousands of C programs (several benchmarks, including the gcc torture test, code from the obfuscated C competition, etc.) Passed 99.2% so far! GCC 4.1.2 passes 99%, ICC 99.4%, Clang 98.3% (no opt.) The most complete formal C semantics The C definition has about 1200 rules. Since a definition is correct by definition, it is important to gain as much confidence in it as possible. Our approach in K is to extensively test our definitions by executing them. In the case of C, the semantics has been tested against several thousands programs in a regression test suite, including gcc’s torture test suite, code from the obfuscated C competitions, as well as many other programs found on the internet which were devised to explore the dark corners of the C language. As of now (Septemeber 2012), the K semantics of C passes 99.2% of the programs in our large test suite. Note that gcc only passes 99%, ICC 99.4%, and Clang 98.3%, all these without optimizations enabled (optimizations reduce these numbers by a few percentages). The reason for which these compilers and even our semantics do not pass all programs, is partly because the semantics of C is not well explained in the manual and allows room for interpretation and confusion. These tools simply do not agree on what a correct C program is. Funny, isn’t it? Particularly when you want to actually verify C programs … At our knowledge, the K semantics of C is the most complete C semantic to date. [POPL’12, PLDI’15]

How slow is it? K Framework supports attaching backends Initial translation to Maude became a backend Java (symbolic) and OCAML (concrete) backends C loop calculating 1 + 2 + … + 5,000,000 Compiled with gcc: 18 ms Fastest hand-written Interpreter: 2 sec (111 x C) K[OCAML]: 14 sec (777 x C, 7 x I) K[Java]: 20 min (66000 x C, 86 x O, 600 x I) K[Maude]: 10 x slower than K[Java] Further improvements coming soon (improving the semantics of C, LLVM backend, compilation) Semantics-based language design feasible !

Deductive program verifier Formal Language Definition (Syntax and Semantics) Symbolic execution

State-of-the-Art Many different program logics for “state” properties: FOL, HOL, Separation logic… Redefine the language using a different semantic approach (Hoare/separation/dynamic logic) Language specific, non-executable, error-prone

State-of-the-Art Thus, these semantics need to be proved sound (and relatively complete) wrt trusted, operational semantics (reference model) Huge effort, few dare to do it; so typically not done But verification tools are developed using them So we have an inherent gap between trusted, operational semantics, and the semantics currently used for program verification

Our Approach Use directly the trusted operational semantics! Formal Language Definition (Syntax and Semantics) Deductive program verifier Symbolic execution Use directly the trusted operational semantics! Language-independent proof system Takes operational semantics as axioms Derives reachability properties Sound and relatively complete for all languages!

Need a means to specify static and dynamic program properties Deductive program verifier Formal Language Definition (Syntax and Semantics) Symbolic execution

Matching Logic for Static Properties Specify properties over program configurations and reason about them using matching logic Ultimate “program logic” for the language in question, specifically crafted for it We only discuss first-order variant here Can be obtained from FOL by collapsing its operation and predicate symbols Collapsing its terms and predicates, into patterns Interpreting symbols in powerset domains

Matching Logic vs. FOL Simpler (no need to distinguish operations from predicates) Same expressiveness, but patterns more succinct than FOL formulae When fixing model(s), quite a convenient notation (captures separation logic)

Separation logic = Matching logic [Map] Consider map model, with some useful axioms Then we can define map patterns “a la SL”

MatchC Example http://matching-logic.org

Sound and complete proof system [RTA’15] Sample derivation: Local reasoning globalized (“structural framing” for free!) Above derivation can be lifted to whole configuration

Need a means to specify static and dynamic program properties Deductive program verifier Formal Language Definition (Syntax and Semantics) Symbolic execution

Reachability Logic for Dynamic Properties [LICS’13], [RTA’14] “Rewrite” rules over matching logic patterns: (generalize to conditional rules) Since patterns generalize terms, matching logic reachability rules capture term rewriting rules Moreover, deals naturally with side conditions: turn into

Expressiveness of Reachability Rules Capture operational semantics rules: Capture Hoare Triples:

Reachability Logic Language-independent proof system for deriving sequents of the form where A (axioms) and C (circularities) are sets of reachability rules Intuitively: symbolic execution with operational semantics + reasoning with cyclic behaviors

Proof System for Reachability Proves any reachability property of any lang., including anything that Hoare logic can (proofs of comparable size) [FM’12] Sound (partially correct) and relatively complete [ICALP’12], [OOPSLA’12], [LICS’13], [RTA’14]

Traditional Verification vs. Our Approach Traditional proof systems: language-specific Our proof system: language-independent

Does It Really Work? Reachability logic implemented in K, generically Evaluated it with the existing semantics of C, Java, and JavaScript, and several tricky programs Q1: Can we specify the desired properties? Q2: Is performance OK?

Time (seconds) spent on applying semantic steps (symbolic execution) Evaluation Results Time (seconds) spent on applying semantic steps (symbolic execution) Time (seconds) spent on domain reasoning (matching logic + querying Z3) Properties very challenging to verify automatically. We only found one such prover for C, based on a separation logic extension of VCC Which takes 260 sec to verify AVL insert (ours takes 210 sec; see above)

Conclusion: It can be done Conclusion: It can be done. Thank you, Jose, for firmly believing it from day 1! Test-case generation Deductive program verifier Parser Interpreter Formal Language Definition (Syntax and Semantics) Model checker Symbolic execution (semantic) Debugger Compiler

Extra Slides

Motivation Goal: verify programs using directly the trusted executable semantics of the language Avoid defining Hoare logic or axiomatic semantics Many existing executable semantics frameworks PLT-REDEX (Findler etal) , MSOS tool (Mosses etal) , OTT (Sewell etal) , Spoofax (Visser etal) , K (Rosu etal) Semantics = rewrite rules over configuration patterns Need: specify properties/patterns/structure of interest over program configurations

Matching Logic - Overview Logic for reasoning about structure Structure defined as algebraic data-types Formulae specify desired structure templates or patterns Formula satisfaction is pattern matching Historical remarks First variant proposed in 2010 (Rosu, Ellison, Schulte) Continuously improved, implemented and applied since then, as part of larger projects on program reasoning Latest and most comprehensive reference: RTA’15 Most general variant; soundness and completeness

Talk Overview Context: Executable language semantics Matching logic The K framework Matching logic Application: Program specification and verification using matching logic

Vision and Objective Deductive program verifier Test-case generation Parser Interpreter Formal Language Definition (Syntax and Semantics) Model checker Symbolic execution (semantic) Debugger K is a language design framework and suite of tools. Its vision is to allow and encourage the language designers to formally define their languages once and for all, using an intuitive and attractive notation, and then obtain essentially for free implementations as well as analysis tools for the defined languages. This is a long-standing dream of the programming language community. Our objective in the K project is to develop the foundations, techniques, and tools to make this dream a reality. Compiler

Current State-of-the-Art in PL Design, Implementation and Analysis Consider some programming language, L Formal semantics of L? Typically skipped: considered expensive and useless Implementations for L Based on some adhoc understanding of what L is Model checkers for L Based on some adhoc encodings/models of L Program verifiers for L Based on some other adhoc encodings/models of L … Before we introduce our approach, let me first explain what the problem is. Consider some real programming language, say L. Do we have any formal semantics for L? Most likely not. This step is typically skipped, being considered by many, unfortunately even programming language experts, too expensive to be worth the effort. In fact, a human readable language semantics can be an excellent means to understand and even learn the language! One problem is, however, that existing semantic approaches are too heavy, non-modular, and hard to digest by humans. Then consider the various implementations and analysis tools for L, even the formal analysis tools. With a lack of semantics, these are based on some adhoc understanding of their developers of what the language L is; more specifically, they build upon adhoc language models, which are hardwired in the tools or systems, but without any guarantee that these models are the right ones, or even sound projections of the actual language semantics.

Example of C Program What should the following program evaluate to? According to the C “standard”, it is undefined GCC4, MSVC: it returns 4 GCC3, ICC, Clang: it returns 3 State-of-the-art formal program verifiers "prove" that this program returns 4 int main(void) { int x = 0; return (x = 1) + (x = 2); } The lack of a formal semantics in implementations and analysis tools does not come without consequences. Consider this two-line C function. Recall that, in C, assignment is an expression construct which evaluates to the assigned expression and, as a side effect, also writes the variable. What does main() return? According to the C “standard”, a rather informal and confusing 700-page document, this program is undefined (because it manifests two unsequenced writes to the same location). However, different C compilers, even different versions of the same compiler, return different results: some 3, others 4. While surprising, this is somewhat acceptable, since compilers are free to optimize assuming that it is programmers’ responsibility that their programs are defined. What is surprising, even unacceptable, is that formal program verifiers actually “prove” that it returns 4! I personally have a hard time understanding how it is even possible to return 4. Anyway, the rhetoric question here is: how can we trust any program verification claims, if advanced formal analysis tools can prove correct obviously wrong two-line programs?

A Formal Semantics Manifesto Languages must have formal semantics! And analysis/verification tools should build on them Otherwise they are adhoc and likely wrong Informal manuals are not sufficient Manuals typically have a formal syntax of the language (in an appendix) Why not a formal semantics appendix as well? Our firm position is that programming languages must have formal semantics. Period! Moreover, analysis or verification tools should build upon formal semantics. Otherwise, they are adhoc and likely wrong. Informal language manuals, or “standards” are simply insufficient. Interestingly, these manuals tend to include a formal syntax of the language, typically in an appendix. Why not a formal semantics appendix as well? In our experience, most programmers are simply scared of semantics, and for good reasons: it takes a lot to digest semantic formalisms, then it is quite boring and tedious to give a semantics to a complete language due to the lack of modularity of most semantic frameworks, and in the end there is not much you can get from or do with a semantics. We are here because we believe that this can be changed.

Recall - First Order Logic

From FOL to Matching Logic

From FOL to Matching Logic Collapse symbols

From FOL to Matching Logic Collapse symbols

From FOL to Matching Logic Collapse terms and predicates

From FOL to Matching Logic Collapse terms and predicates

From FOL to Matching Logic Interpret symbols into powerdomains

From FOL to Matching Logic Interpret symbols into powerdomains

Matching Logic vs. FOL Simpler (no need to distinguish operations from predicates) Same expressiveness, but patterns more succinct than FOL formulae When fixing model(s), quite a convenient notation (captures separation logic)

Bottom Line No distinction between function and predicate symbols; they build patterns In models, patterns evaluate to sets of elements, namely those that match them Examples , written , matched by singletons of sort s matched by successor of x elements are either zero or successors matched by all linked lists in the heap starting with pointer x and holding mathematical sequence S

Useful Sugar Derived constructs Definedness, equality, membership Either the empty set (when  empty) or otherwise the total set (when  non-empty) Sort subscripts and superscripts can be inferred from the context, so we do not write them

We write it using the functional notation: More Sugar Functions (recovering “operation” symbols) Similarly we can define partial functions, total relations, etc. Algebraic specification and FOL subsumed notationally. For example: We write it using the functional notation:

Matching Logic vs. Separation Logic Matching logic achieves separation through matching at the structural (term) level, not through special logical connectives (*). Separation logic = Matching logic [heap] OOPSLA’12, RTA’15 Matching logic realizes separation at all levels of the configuration, not only in the heap the heap was only 1 out of the 120 cells in C’s def.

Examples of Patterns  |A| >1 x points to sequence A with |A|>1, and the reversed sequence rev(A) has been output untrusted()can only be called from trusted()  |A| >1

Reduction to Predicate Logic= (see paper) Like FOL, ML can be reduced to predicate logic Explosion in size, new quantifiers; impractical