490 likes | 495 Views
Checking correctness properties of object-oriented programs. K. Rustan M. Leino Microsoft Research, Redmond, WA. Lecture 0 EEF summer school on Specification, Refinement, and Verification 19 Aug 2002, Turku, Finland. A problem. W. !. !. !. !. !. !. A more troublesome problem.
E N D
Checking correctness properties of object-oriented programs K. Rustan M. LeinoMicrosoft Research, Redmond, WA Lecture 0EEF summer school on Specification, Refinement, and Verification19 Aug 2002, Turku, Finland
! ! ! ! ! !
A more troublesome problem • Software construction and maintenance are expensive • Reliability is an issue
Vision • Increased programmer productivity and program reliability through increased rigor Record design decisions + Utilize automatic checking= Detect errors and improve maintainability
User’s view Program checker Error messages Program with specifications public class Bag { private /*@non_null*/ int[] a; private int n; //@ invariant 0 <= n && n <= a.length; public Bag(/*@non_null*/ int[] initialElements) { n = initialElements.length; a = new int[n]; System.arraycopy(initialElements, 0, a, 0, n); } public void add(int x) { if (n == a.length) { int[] b = new int[2*(a.length+1)]; System.arraycopy(a, 0, b, 0, n); a = b; } a[n] = x; n++; } public int extractMin() { int m = Integer.MAX_VALUE; int mindex = 0; for (int i = 0; i < n; i++) { if (a[i] < m) { mindex = i; m = a[i]; } } if (0 < n) { n--; a[mindex] = a[n]; } return m; } // The program text continues down here, but if you’re // reading this, you probably aren’t paying attention to // the talk. Bag.java:18: Array index possibly too large
Extended Static Checker for Java (ESC/Java) • Built at Compaq SRC • Input: Java + user-supplied annotations • Annotation language captures programmer design decisions • Powered by program semantics and automatic theorem proving • Performs modular checking
Program checker design tradeoffs • Missed errors • Spurious warnings • Annotation overhead • Performance
Tool architecture Annotated Java program Translator Verification condition Valid Automatic theorem prover Resource exhausted Counterexample context Post processor Warning messages
Tool architecture, detail Annotated Java program Sugared command Translator Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages
Annotated Java program Annotated Java program Sugared command Sugared command Primitive command Translator Translator Primitive command Passive command Passive command Verification condition Verification condition Automatictheorem prover Automatic theorem prover Counterexample context Counterexample context Post processor Post processor Warning messages Warning messages Tool architecture, detail
Annotation language Annotated Java program • Simple • non_null • Method annotations • requires E; • modifies w; • ensures P; • exsures (T x) Q; • Object invariants • invariant E; Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Simple • non_null • Method annotations • requires E; • modifies w; • ensures P; • exsures (T x) Q; • Object invariants • invariant E; Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Specification expressions • side-effect free Java expressions • no ++, no method calls • \result, \old(E) • ensures\result == \old(x); • ==> • (\forall T x; P), (\exists T x; P) • (\forall int j; 0 <= j && j < n ==> a[j] > 0); • \typeof(E), \type(T), <: • requires\typeof(x) == \typeof(this); Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Specification expressions • side-effect free Java expressions • no ++, no method calls • \result, \old(E) • ensures\result == \old(x); • ==> • (\forall T x; P), (\exists T x; P) • (\forall int j; 0 <= j && j < n ==> a[j] > 0); • \typeof(E), \type(T), <: • requires\typeof(x) == \typeof(this); Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Concurrency • monitored_by lock • /*@ monitored_bythis */ long x; • \lockset[lock] • requires\lockset[this]; • lock0 < lock1 • \max(\lockset) • requires \max(\lockset) < this; Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Concurrency • monitored_by lock • /*@ monitored_bythis */ long x; • \lockset[lock] • requires\lockset[this]; • lock0 < lock1 • \max(\lockset) • requires \max(\lockset) < this; Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Ghost variables • ghostpublic T x; • ghostpublic int objectState; • ghostpublic\TYPE elementType; • set x = E; • set objectState = Open; • set elementType = \type(T); Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Ghost variables • ghostpublic T x; • ghostpublic int objectState; • ghostpublic\TYPE elementType; • set x = E; • set objectState = Open; • set elementType = \type(T); Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Annotation language Annotated Java program • Miscellaneous • assert E; • assume E; • assume x >= 0; // because x == y*y • nowarn • x = a[j]; //@ nowarn • axiom E; • axiom (\forall int x; x >> 2 >= 0); Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Sugared commands Annotated Java program • S,T ::= assert E | assume E | x = E | raise | S ; T | S ! T | S [] T | loop {inv E} S T end | call x = t.m(E) | … Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Sugared commands Annotated Java program • x = t.f.g; assert t != null; tmp = select(f, t); assert tmp != null; x = select(g, tmp) • if (x < 0) { x = -x; }/*@ assert x >= 0; */ ( assume x < 0; x = -x [] assume !(x < 0) ); assert x >= 0 Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Sugared commands Annotated Java program • x = t.f.g; assert lblneg(“Null@58.9”, t != null); tmp = select(f, t)); assert lblneg(“Null@58.11”, tmp != null); x = select(g, tmp) • if (x < 0) { x = -x; }/*@ assert x >= 0; */ ( assume x < 0;assume lblpos(“Then^280:7”, true); x = -x [] assume !(x < 0);assume lblpos(“Else^280:7”, true) ); assert x >= 0 Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Primitive commands Annotated Java program • S,T ::= assert E | assume E | x = E | raise | S ; T | S ! T | S [] T | loop {inv E} S T end | call x = t.m(E) | … Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Primitive commands Annotated Java program • //@ requires Pre; modifies w; ensures Post;void m(U u); • call x = t.m(E) var u in u = E; assert Pre; var w0 in w0 = w; havoc w; assume Post end end Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
| raise | S ; T | S ! T | S [] T Passive commands Annotated Java program • S,T ::= assert E | assume E | x = E Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Passive commands Annotated Java program • if (x < 0) { x= -x; }/*@ assert x >= 0; */ ( assume x0 < 0; assume x1 == -x0;assume x2 == x1 [] assume !(x0 < 0);assume x2 == x0 ); assert x2 >= 0 Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Weakest preconditions Annotated Java program • wp(assert E, Q) = E && Q • wp(assume E, Q) = E ==> Q • wp(S;T, Q) = wp(S, wp(T,Q)) • wp(S [] T, Q) = wp(S, Q) && wp(T, Q) • wp(S, Q) = wp(S, true) && wlp(S, Q) • wlp(S, Q) = wlp(S, false) || Q Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Verification condition Annotated Java program • Universal background predicate • (FORALL (t) (<: t t)) • Type-specific background predicate • (<: T_T |T_java.lang.Object|) • Verification condition: BPUniv && BPT ==> VCmethod Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
(BG_PUSH (AND (<: T_T |T_java.lang.Object|) (EQ T_T (asChild T_T |T_java.lang.Object|)) (DISTINCT arrayType |T_boolean| |T_char| |T_byte| |T_short| |T_int| |T_long| |T_float| |T_double| |T_.TYPE| T_T |T_java.lang.Object|))) (EXPLIES (LBLNEG |vc.T.abs.2.2| (IMPLIES (AND (EQ |elems@pre| elems) (EQ elems (asElems elems)) (< (eClosedTime elems) alloc) (EQ LS (asLockSet LS)) (EQ |alloc@pre| alloc)) (NOT (AND (EQ |@true| (is |x:2.21| T_int)) (OR (AND (OR (AND (< |x:2.21| 0) (LBLPOS |trace.Then^0,3.15| (EQ |@true| |@true|)) (EQ |x:3.17| (- 0 |x:2.21|)) (EQ |x:2.21<1>| |x:3.17|)) (AND (NOT (< |x:2.21| 0)) (LBLPOS |trace.Else^1,3.4| (EQ |@true| |@true|)) (EQ |x:2.21<1>| |x:2.21|))) (NOT (LBLNEG |Assert@4.8| (>= |x:2.21<1>| 0)))) (AND (OR (AND (< |x:2.21| 0) (LBLPOS |trace.Then^0,3.15| (EQ |@true| |@true|)) (EQ |x:3.17| (- 0 |x:2.21|)) (EQ |x:2.21<1>| |x:3.17|)) (AND (NOT (< |x:2.21| 0)) (LBLPOS |trace.Else^1,3.4| (EQ |@true| |@true|)) (EQ |x:2.21<1>| |x:2.21|))) (LBLNEG |Assert@4.8| (>= |x:2.21<1>| 0)) (NOT (LBLNEG |Exception@5.2| (EQ |ecReturn| |ecReturn|))))))))) (AND (DISTINCT |ecReturn|))) Verification condition Annotated Java program • class T { static int abs(int x) { if (x < 0) { x = -x; } //@ assert x >= 0; } } Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Theorem prover: “Simplify” Annotated Java program • Nelson-Oppen cooperating decision procedures • conguence closure • linear arithmetic • partial orders • quantifiers • Key features: • automatic: no user interaction • refutation based: searches for counterexamples • heuristics tuned for program checking • labels • time limit Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Counterexamples and warnings Annotated Java program • Counterexample: labels: (|IndexTooBig@26.5| |vc.Bag.add.20.2| |trace.Then^0,21.23|) context: (AND (NEQ |tmp1!a:23.23| null) (NEQ this null) (EQ |alloc@pre| alloc) (EQ |tmp4!n:26.6| 0) … (<= alloc (vAllocTime |tmp3!a:26.4|)) ) • Bag: add(int) ...------------------------------------------------------------------------Bag.java:26: Warning: Array index possibly too large (IndexTooBig) a[n] = x;^Execution trace information: Executed then branch in "Bag.java", line 21, col 23.------------------------------------------------------------------------ Sugared command Primitive command Translator Passive command Verification condition Automatictheorem prover Counterexample context Post processor Warning messages
Experience: annotations • Capture common design decisions • Suggested immediately by warnings • Overhead: 4-10% of source code • ~1 annotation per field or parameter • Most common annotations: • non_null • container element types
Experience: performance • 50% of all methods: < 0.5 s • 80% of all methods: < 1 s • time limit: 300 s • total time for Javafe (~40kloc): 65 min.
Related work • ESC/Modula-3 • Full functional specification and verification • JML, LOOP, B, Penelope, … • Languages and language features • Euclid, Eiffel, Escher, Guava, Vault, Cqual, … • LCLint, refinement types, Types against races, … • Other checking techniques • Abstract interpretation, PREfix, SLAM, Bandera, Java PathFinder 2, Canvas, ESP, AST Toolkit, Metal, …
Conclusions • Using program semantics and automatic decision procedures for program analysis works! • Cost effective?
What’s needed? • Semantics of programming language • Specification language • Programming methodology and disciplines • Decision procedures • Property inference • Download ESC/Java (tool, documentation, sources): research.compaq.com/SRC/esc
References Overview papers of ESC tools and technology • Cormac Flanagan, K. Rustan M. Leino, Mark Lillibridge, Greg Nelson, James B. Saxe, and Raymie Stata. “Extended static checking for Java”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 234-245, ACM, May 2002. • David L. Detlefs, K. Rustan M. Leino, Greg Nelson, and James B. Saxe. Extended static checking. Research Report 159, Compaq SRC, Dec. 1998. • K. Rustan M. Leino. “Extended static checking: A ten-year perspective”. In Reinhard Wilhelm, ed., Informatics—10 Years Back, 10 Years Ahead, volume 2000 of LNCS, pp. 157-175. Springer, Jan. 2001.
References ESC/Java annotation language • K. Rustan M. Leino, Greg Nelson, and James B. Saxe. ESC/Java User’s Manual. Technical Note 2000-002, Compaq SRC, Oct. 2000.
References ESC/Java checking technology • Edsger W. Dijkstra. A Discipline of Programming. Prentice Hall, 1976. • K. Rustan M. Leino, James B. Saxe, and Raymie Stata. “Checking Java programs via guarded commands”. In Bart Jacobs, et al., eds., Formal Techniques for Java Programs, Technical Report 251, FernUniversität Hagen, May 1999. • Cormac Flanagan and James B. Saxe. “Avoiding exponential explosion: Generating compact verification conditions”. In 28th POPL, SIGPLAN Notices 36(3), pp. 193-205, ACM, Mar. 2001. • Greg Nelson. Techniques for Program Verification. PhD thesis, Stanford. Technical Report CSL-81-10, Xerox PARC, Jun. 1981. • Todd Millstein. “Toward more informative ESC/Java warning messages”. In James Mason, ed., Selected 1999 SRC summer intern reports, Technical Note 1999-003, Compaq SRC, 1999.
References Related work on full functional specification and verification • JML home page: http://www.cs.iastate.edu/~leavens/JML.html • Gary T. Leavens, Albert L. Baker, and Clyde Ruby. Preliminary Design of JML: A Behavioral Interface Specification Language for Java. Department of Computer Science, Iowa State University, TR #98-06r, Aug. 2002. • Gary T. Leavens, K. Rustan M. Leino, Erik Poll, Clyde Ruby, and Bart Jacobs. JML: notations and tools supporting detailed design in Java. In OOPSLA '00 Companion, Minneapolis, Minnesota, pp. 105-106. ACM. Also available as Department of Computer Science, Iowa State University, TR #00-15, Aug. 2000. • Joachim van den Berg and Bart Jacobs. “The LOOP compiler for Java and JML”. In T. Margaria and W. Yi, eds., Tools and Algorithms for the Construction and Analysis of Software (TACAS). Volume 2031 of LNCS, pp. 299-312, Springer, 2001.
References Related work on full functional specification and verification (cont.) • J.-R. Abrial. The B-Book: Assigning Programs to Meanings. Cambridge University Press, 1996. • David Guaspari, Carla Marceau, and Wolfgang Polak. “Formal Verification of Ada Programs”. In IEEE Transactions on Software Engineering 16(9), pp. 1058-1075, Sep. 1990. • …
References Related work on languages and language features • Butler W. Lampson, James J. Horning, Ralph L. London, James G. Mitchell, and Gerald J. Popek. Report on the Programming Language Euclid. Technical Report CSL-81-12, Xerox PARC, Oct. 1981. • Bertrand Meyer. Object-oriented Software Construction. International Series in Computer Science, Prentice Hall, 1988. • Escher Technologies, Inc. Getting started with Perfect. Available from http://www.eschertech.com, 2001. • David Evans, John V. Guttag, James J. Horning, and Yang Meng Tan. “LCLint: A Tool for Using Specifications to Check Code”. In SIGSOFT FSE 1994, SIGSOFT Software Engineering Notes 19(5), pp. 87-96, ACM, Dec. 1994. • Robert DeLine and Manuel Fähndrich. “Enforcing high-level protocols in low-level software”. In PLDI ’01, SIGPLAN Notices 36(5), pp. 59-69, ACM, May 2001.
References Related work on languages and language features (cont.) • Jeffrey S. Foster, Tachio Terauchi, and Alexander Aiken. “Flow-sensitive type qualifiers”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 1-12, ACM, May 2002. • Hongwei Xi and Frank Pfenning. “Dependent Types in Practical Programming”. In 26th POPL, pp. 214-227, ACM Press, Jan. 1999. • Cormac Flanagan and Stephen N. Freund. “Type-based race detection for Java”. In PLDI ’00, SIGPLAN Notices 35(5), pp. 219-232, ACM, May 2000. • David F. Bacon, Robert E. Strom, and Ashis Tarafdar. “Guava: A Dialect of Java without Data Races”. In OOPSLA ’00, SIGPLAN Notices 35(10), pp. 382-400, ACM, Oct. 2000.
References Related work on other checking techniques • Patrick Cousot and Radhia Cousot. “Abstract interpretation: a unified lattice model for static analysis of programs by construction or approximation of fixpoints”. In 4th POPL, pp. 238-252, ACM, Jan. 1977. • William R. Bush, Jonathan D. Pincus, and David J. Sielaff. “A static analyzer for finding dynamic programming errors”, Software—Practice & Experience 30(7), pp. 775-802, Jun. 2000. • Thomas Ball and Sriram K. Rajamani. “Automatically validating temporal safety properties of interfaces”. In Matthew B. Dwyer, ed., Model Checking Software, 8th International SPIN Workshop, volume 2057 of LNCS, pp. 103-122, Springer, 2001. • James C. Corbett, Matthew B. Dwyer, John Hatcliff, Shawn Laubach, Corina S. Pasareanu, Robby, and Hongjun Zheng. “Bandera: extracting finite-state models from Java source code”. In ICSE 2000, pp. 439-448, ACM, 2000.
References Related work on other checking techniques (cont.) • Willem Visser, Klaus Havelund, Guillaume P. Brat, and Seungjoon Park. “Model checking programs”. In 15th IEEE International Conference on Automated Software Engineering (ASE ’00), pp. 3-12, IEEE Computer Society, 2000. • Manuvir Das, Sorin Lerner, and Mark Seigle. “ESP: Path-Sensitive Program Verification in Polynomial Time”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 57-68, ACM, May 2002. • G. Ramalingam, Alex Warshavsky, John Field, Deepak Goyal, and Mooly Sagiv. “Deriving Specialized Program Analyses for Certifying Component-Client Conformance”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 83-94, ACM, May 2002. • Seth Hallem, Benjamin Chelf, Yichen Xie, and Dawson R. Engler. “A System and Language for Building System-Specific, Static Analyses”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 69-82, ACM, May 2002. • …