Modular and Verified Automatic Program Repair Francesco Logozzo, Thomas Ball RiSE - Microsoft Research Redmond.

Slides:



Advertisements
Similar presentations
1 Verification by Model Checking. 2 Part 1 : Motivation.
Advertisements

Writing specifications for object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 21 Jan 2005 Invited talk, AIOOL 2005 Paris,
Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond,
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Challenges in increasing tool support for programming K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 23 Sep 2004 ICTAC Guiyang, Guizhou, PRC joint.
Copyright W. Howden1 Programming by Contract CSE 111 6/4/2014.
De necessariis pre condiciones consequentia sine machina P. Consobrinus, R. Consobrinus M. Aquilifer, F. Oratio.
An Abstract Interpretation Framework for Refactoring P. Cousot, NYU, ENS, CNRS, INRIA R. Cousot, ENS, CNRS, INRIA F. Logozzo, M. Barnett, Microsoft Research.
The Spec# programming system K. Rustan M. Leino Microsoft Research, Redmond, WA, USA Distinguished Lecture Series Max Planck Institute for Software Systems.
Abstraction of Source Code (from Bandera lectures and talks)
Semantics Static semantics Dynamic semantics attribute grammars
A Program Transformation For Faster Goal-Directed Search Akash Lal, Shaz Qadeer Microsoft Research.
Things to Remember When Developing 64-bit Software OOO "Program Verification Systems"
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
CodeContracts & Clousot Francesco Logozzo - Microsoft Mehdi Bouaziz – ENS.
Giving a formal meaning to “Specialization” In these note we try to give a formal meaning to specifications, implementations, their comparisons. We define.
Mahadevan Subramaniam and Bo Guo University of Nebraska at Omaha An Approach for Selecting Tests with Provable Guarantees.
Data Abstraction II SWE 619 Software Construction Last Modified, Spring 2009 Paul Ammann.
ISBN Chapter 3 Describing Syntax and Semantics.
1 Semantic Description of Programming languages. 2 Static versus Dynamic Semantics n Static Semantics represents legal forms of programs that cannot be.
1 Basic abstract interpretation theory. 2 The general idea §a semantics l any definition style, from a denotational definition to a detailed interpreter.
CS 330 Programming Languages 09 / 18 / 2007 Instructor: Michael Eckmann.
Houdini: An Annotation Assistant for ESC/Java Cormac Flanagan and K. Rustan M. Leino Compaq Systems Research Center.
OOP #10: Correctness Fritz Henglein. Wrap-up: Types A type is a collection of objects with common behavior (operations and properties). (Abstract) types.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
CS 330 Programming Languages 09 / 16 / 2008 Instructor: Michael Eckmann.
Describing Syntax and Semantics
CS 267: Automated Verification Lecture 13: Bounded Model Checking Instructor: Tevfik Bultan.
Regression testing Tor Stållhane. What is regression testing – 1 Regression testing is testing done to check that a system update does not re- introduce.
Dr. Pedro Mejia Alvarez Software Testing Slide 1 Software Testing: Building Test Cases.
Pentagons: A Weakly Relational Abstract Domain for the Efficient Validation of Array Accesses Francesco Logozzo, Manuel Fahndrich Microsoft Research, Redmond.
Software Engineering Prof. Dr. Bertrand Meyer March 2007 – June 2007 Chair of Software Engineering Static program checking and verification Slides: Based.
A Parametric Segmentation Functor for Fully Automatic and Scalable Array Content Analysis Patrick Cousot, NYU & ENS Radhia Cousot, CNRS & ENS & MSR Francesco.
1 Lecture 14 Chapter 18 - Recursion. 2 Chapter 18 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing.
1 Chapter 13 Recursion. 2 Chapter 13 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing Recursive.
Recursion Textbook chapter Recursive Function Call a recursive call is a function call in which the called function is the same as the one making.
SWE 619 © Paul Ammann Procedural Abstraction and Design by Contract Paul Ammann Information & Software Engineering SWE 619 Software Construction cs.gmu.edu/~pammann/
DEBUGGING. BUG A software bug is an error, flaw, failure, or fault in a computer program or system that causes it to produce an incorrect or unexpected.
CSE 425: Data Types I Data and Data Types Data may be more abstract than their representation –E.g., integer (unbounded) vs. 64-bit int (bounded) A language.
Introduction to Problem Solving. Steps in Programming A Very Simplified Picture –Problem Definition & Analysis – High Level Strategy for a solution –Arriving.
Semantics In Text: Chapter 3.
COP4020 Programming Languages Introduction to Axiomatic Semantics Prof. Robert van Engelen.
Java Basics Hussein Suleman March 2007 UCT Department of Computer Science Computer Science 1015F.
Spec# Andreas Vida. Motivation Correct and maintainable software Correct and maintainable software Cost effective software production Cost effective software.
CPSC 873 John D. McGregor Session 9 Testing Vocabulary.
Lecture 5 1 CSP tools for verification of Sec Prot Overview of the lecture The Casper interface Refinement checking and FDR Model checking Theorem proving.
1 Recursion. 2 Chapter 15 Topics  Meaning of Recursion  Base Case and General Case in Recursive Function Definitions  Writing Recursive Functions with.
CPSC 871 John D. McGregor Module 8 Session 1 Testing.
Error Explanation with Distance Metrics Authors: Alex Groce, Sagar Chaki, Daniel Kroening, and Ofer Strichman International Journal on Software Tools for.
C HAPTER 3 Describing Syntax and Semantics. D YNAMIC S EMANTICS Describing syntax is relatively simple There is no single widely acceptable notation or.
Announcements Assignment 2 Out Today Quiz today - so I need to shut up at 4:25 1.
CPSC 372 John D. McGregor Module 8 Session 1 Testing.
The PLA Model: On the Combination of Product-Line Analyses 강태준.
Jeremy Nimmer, page 1 Automatic Generation of Program Specifications Jeremy Nimmer MIT Lab for Computer Science Joint work with.
Modular Decomposition, Abstraction and Specifications
Weakest Precondition of Unstructured Programs
Spring 2016 Program Analysis and Verification
Reasoning About Code.
State your reasons or how to keep proofs while optimizing code
Symbolic Implementation of the Best Transformer
Lecture 5 Floyd-Hoare Style Verification
Test Case Purification for Improving Fault Localization
Programming Languages 2nd edition Tucker and Noonan
Semantics In Text: Chapter 3.
NASA Secure Coding Rules
Chapter 18 Recursion.
Assertions References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 4/25/2019.
Predicate Abstraction
Information Security CS 526
Programming Languages 2nd edition Tucker and Noonan
Presentation transcript:

Modular and Verified Automatic Program Repair Francesco Logozzo, Thomas Ball RiSE - Microsoft Research Redmond

The problem Programs have bugs Bug finders, static analyzers and verifiers, etc. help spot them However, they provide little or no help for fixing the bugs The goal Bring static analyses to the next level Report both the warning and the fix for it While the programmer is authoring the program

Which bugs? We focus on possible bugs reported by static analyzers/verifiers Motto: “We can only fix what we can prove correct” For instance, the CodeContracts static checker (Clousot) reports Contract violations Common runtime errors: Null pointers, division by zero, arithmetic overflows … We should not only report the warning, but also a set of fixes for it Increase adoption Overcome the scaring long list of warnings Help understanding the origin of the warning Code is clearer than an error trace

What is a code repair? In testing, use the test suite T as a specification The buggy program fails at least one test in T The repaired program succeeds all the tests in T The repaired program is obtained by some mutation of the buggy program This definition is unsuited for real-time program verification It requires running the program At design time, the program is incomplete, does not compile Test running can be expensive The repair is as good as the test suite T Example: fix assert(e) with if(e) assert(e)

Verified code repairs We propose a different yet semantic notion of repairs A verified repair reduces the bad runs while increasing the good runs A good run is one that satisfies the specification Assertion, precondition, runtime condition … A bad run is one that violates the specification Consequences: When we repair a program we cannot remove any good behavior There can be multiple, non comparable, repairs No best repair in general!

Example

From the.NET library public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { if (c == null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … }

Repair #1: change the guard public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { if (c != null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … }

Repair #2: Add precondition public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { Contract.Requires(c != null); if (c == null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … }

What if the code was like that? public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { if (c == null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … } else { var area = c.Width * c.Height; // … }

Changing the guard removes good runs public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { if (c != null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … } else { var area = c.Width * c.Height; // … } This is not a verified repair!

Adding a precondition removes bad runs public void ValidateOwnerDrawRegions(ComboBox c, Rectangle updateRegionBox) { Contract.Requires(c != null); if (c == null) { var r = new Rectangle(0, 0, c.Width, c.Height); // … } else { var area = c.Width * c.Height; // … } This is a verified repair!

Formalization

Program analysis and Code repairs There are three components in program analysis The program text The specification, the property to be specified The analysis result, the semantic knowledge about the program execution The (usual) verification problem is “Check that the analysis result guarantees that the program meets its specification" The (new) verified code repair problem is “Refine the program using the analysis result so that it meets its specification” Related, but different than program synthesis

Repairs are property-dependent In static analysis tools, the knowledge is given by the inferred abstract state Similar for tools based on model checking, deductive methods, types … The abstract state belongs to some abstract domain The abstract domain encodes some property of interest Idea: An abstract domain should also know how to repair the program Therefore the verified code repairs depend are property-dependent E.g., often we cannot repair non-functional bugs like performance

Some definitions A run is an execution trace, i.e., a sequence of concrete states For all programs P, we partition the set of runs into G(P), the good runs B(P), the bad runs We do not consider infinite traces here Technically possible, complicates the exposition A repair r is a program transformation with “some correctness condition” Next: define the “correctness condition”

Verified repairs? We may be tempted to define a verified repair as G(P) ⊆ G(r(P)) and B(P) ⊇ B(r(P)) But this definition is too strong! It would work only for trivial repairs Execution traces capture too much information They are too fine grained, the repair may add new assertions Solution? Perform abstractions! The abstraction captures the behaviors we want to preserve and to correct Intuition: Repair up to some observable property

Verified code repairs! Idea: compare only the assertion runs of P and r(P) Forget about intermediate states, keep only the states with the assertions Define an abstraction function α V in two steps 1. Remove all the states but those containing an assertion 2. Remove all assertions in r(P) but not in P We want to compare only the “old” assertions Definition: r is a verified code repair if α V (G(P)) ⊆ α V (G(r(P))) and α V (B(P)) ⊃ α V (B(r(P)))

Consequences Identity is not a repair Runs of failing assertions should always decrease For a given program there may be several distinct repairs r 1,r 2,r 3 … The relation induces an order on programs P ⊑ r 1 (P) ⊑ r 1 (r 2 (P)) … Repairs can be iterated to a fixpoint In general there is no least fixpoint No diamond property

Weak verified repairs Further abstraction α W to Have sets of states instead of sets of traces Forget the casual relationship between states Have assertion truth instead of the particular values of the variables Definition: r is a weak verified repair if α W ∘ α V (G(P)) ⊆ α W ∘ α V (G(r(P))) and α W ∘ α V (B(P)) ⊃ α W ∘ α V (B(r(P))) Intuition: a weak verified repair Decreases the number of assertion violations without introducing regressions Enables more repairs but with weaker guarantees in the concrete

Methodology Design an abstract domain as usual Abstract elements, domain operations, widening, transfer functions… Design a code repair for the properties captured by the new abstract domain Remember, code repairs are property-specific Categorize your code repair: Strong or weak verified repair?

In practice

Verified repairs from a static analyzer Run the static analyzer to infer the abstract states For each assertion in the program Ask the abstract domains if they can prove it If they cannot, ask the abstract domains to provide a code repair Providing a code repair may require re-running the analysis To check that there are no new warnings

Repairing floats Clousot infers this.f : f64 tmp : fext Emits warning for precision mismatch Suggests the verified repair: tmp = (double)(a + b) double f; void SimpleError(double a, double b) { var tmp = a + b; this.f = tmp; if (this.f == tmp) { … } } ⊥ f32f64 fext ⊤

Repairing of overflows int BinarySearch(int[] array, int value) { Contract.Requires(array != null); int index, mid; var inf = 0; var sup = array.Length - 1; while (inf <= sup) { index = (inf + sup) / 2; mid = array[index]; if (value == mid) return index; if (mid < value) inf = index + 1; else sup = index - 1; } return -1; } Clousot infers the loop invariant 0 ≤ inf ≤ sup < array.Length ≤ We want to repair the arithmetic overflow Suggest the verified repair: inf + (sup – inf)/2 Guaranteed to not overflow Because of the inferred loop invariant Details in the paper

Example of a common error Assume: 0 ≤ x, 0 ≤ y, 0 ≤ z Then x + y < z may overflow Exactly, x + y < z in computer precision does not have the same meaning than in ℤ We derive a non-overflowing expression like that (x ! + y ! ) ? < z ! as 0 ≤ x, then –x cannot underflow =y ! < (z ! +(– x ! ) ! ) ? as 0 ≤ z and 0 ≤ x, then z – x cannot underflow =y ! < (z ! +(– x ! ) ! ) !

Verified repairs in Clousot Contracts Missing preconditions, postconditions, external assumptions, purity annotations Constant and object initialization Guards Buffer overflows Arithmetic overflows Floating point comparisons … Details in the paper

Experience

Implementation Clousot is the underlying static analyzer Part of the CodeContracts tools, widely used More than 75K external downloads Based on abstract interpretation Analyze each method in isolation Infer loop invariants, preconditions, postconditions, and object invariants Use the inferred facts to discharge proof obligations On failure suggest a verified code repair Runs at design time Came to see the demo!

Raw numbers Analyze.NET main libraries Check Contracts, non-null, overflows … Analyze 6+ methods/seconds Infer 7.5 repairs/second

Precision Verified 89% Don’t know 11% Verified repairs 9% Warnings 2%

Conclusions

Bring static analysis to the next level Simple flood of warnings is not practical Suggest verified and modular repairs Verified repairs increase the good executions while reducing the bad ones Up to some observable property Verified repairs are property dependent Implemented on a real static analyzer Get a repair for 80.9% of the warnings Come to see the demo in a couple of minutes!!!!