350 likes | 525 Views
Extended Static Checking for Java. Cormac Flanagan K. Rustan M. Leino Mark Lillibridge Greg Nelson James B. Saxe Raymie Stata Compaq SRC. 18 June 2002 PLDI’02, Berlin, Germany. Vision. Increased programmer productivity and program reliability through increased rigor. Record design decisions
E N D
Extended Static Checkingfor Java Cormac FlanaganK. Rustan M. LeinoMark LillibridgeGreg NelsonJames B. SaxeRaymie Stata Compaq SRC 18 June 2002PLDI’02, Berlin, Germany
Vision • Increased programmer productivity and program reliability through increased rigor Record design decisions + Utilize automatic checking= Detect errors and improve maintainability ESC/Java
User’s view ESC/Java Warning messages Annotated Java program 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 ESC/Java
ESC/Java distinguishing features • Modular checking • Annotation language captures design decisions • Powered by automatic theorem prover • Not decidable ESC/Java
Demo ESC/Java
Design tradeoffs • Missed errors • Spurious warnings • Annotation overhead • Performance ESC/Java
Tool architecture Annotated Java program Translator Verification condition Valid Automatic theorem prover Resource exhausted Counterexample context Post processor Warning messages ESC/Java
Tool architecture, detail Annotated Java program Sugared command Translator Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor ESC/Java 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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
Annotation language Annotated Java program • Concurrency • monitored_by E • /*@ 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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
| 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 ESC/Java
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 ESC/Java
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 ESC/Java
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 ESC/Java
(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 ESC/Java
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 ESC/Java
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 ESC/Java
Experience Errors found • Javafe (ESC/Java front end, ~40kloc) ~12 • Mercator (web crawler) 2 • Sparse matrix library 2 • Annotation wizard 2 • Performance plotting program 1 • … … • External user experience … • Experience with automatically inferred annotations ESC/Java
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. ESC/Java
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 ESC/Java
Related work • ESC/Modula-3 • [Detlefs, Leino, Nelson, Saxe; 1992-1996] • Full functional Java specification and verification • JML, LOOP • Languages and language features • Euclid, Eiffel, B, 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, … • Tools built on ESC/Java • Daikon, Houdini ESC/Java
Conclusions • Theorem proving for program analysis works! • Annotations express design decisions • Cost effective? • Ready for use by disciplined programming teams and in teaching • Future challenges: • beyond method-modular checking • more specification methodologies • Download ESC/Java: research.compaq.com/SRC/escSources now available, too! ESC/Java