Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Extended Static Checking for Java or Light-weight formal methods: from objects to components K. Rustan M. Leino Microsoft Research, Redmond, WA Joint work with Cormac Flanagan, Mark Lillibridge, Greg Nelson, James B. Saxe, Raymie Stata Compaq SRC 6 Nov 2002 FMCO 2002, Leiden, The Netherlands Formal methods coverage program verification extended static checking decidability ceiling light-weight formal methods type checking effort Note: Illustration not to scale User’s view Annotated Java program ESC/Java Warning messages 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++; } Bag.java:18: Array index possibly too large Bag.java:45: Precondition possibly violated Goals of ESC/Java Practical static checking Detect common run-time errors null dereferences array bounds type casts race conditions deadlocks ... Modular checking ESC/Java distinguishing features Annotation language captures design decisions Powered by automatic theorem prover Not decidable Not sound or complete Performs modular checking Method-modular checking Check that each method satisfies its specification, assuming that all called routines satisfy theirs Reason about implementation when it is written, not when it is used or extended Modular checking Interface check Client check Method body check Client Design tradeoffs Missed errors Spurious warnings Annotation overhead Performance Tool architecture Annotated Java program Translator Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Valid Resource exhausted Tool architecture, detail Translator Annotated Java program Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Annotated Java program Tool architecture, detail Annotated Java program Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Translator Translator Sugared command Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Annotation language Annotated Java program Translator Sugared command Primitive command Passive command Automatic theorem prover Post processor Warning messages non_null Method annotations Verification condition Counterexample context Simple requires E; modifies w; ensures P; exsures (T x) Q; Object invariants invariant E; Annotation language Annotated Java program Translator Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Specification expressions side-effect free Java expressions \result, \old(E) ensures \result == \old(x); ==> (\forall T x; P), (\exists T x; P) no ++, no method calls (\forall int j; 0 <= j && j < n ==> a[j] > 0); \typeof(E), \type(T), <: requires \typeof(x) == \typeof(this); Annotation language Annotated Java program Translator Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Concurrency monitored_by lock \lockset[lock] /*@ monitored_by this */ long x; requires \lockset[this]; lock0 < lock1 \max(\lockset) requires \max(\lockset) < this; Annotation language Annotated Java program Translator Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Concurrency monitored_by lock \lockset[lock] /*@ monitored_by this */ long x; requires \lockset[this]; lock0 < lock1 \max(\lockset) requires \max(\lockset) < this; Annotation language Annotated Java program Translator Sugared command Primitive command Ghost variables ghost public int objectState; ghost public \TYPE elementType; Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages ghost public T x; set x = E; set objectState = Open; set elementType = \type(T); Annotation language Annotated Java program Translator Sugared command Primitive command Ghost variables ghost public int objectState; ghost public \TYPE elementType; Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages ghost public T x; set x = E; set objectState = Open; set elementType = \type(T); Annotation language Annotated Java program Translator Sugared command Primitive command Miscellaneous Passive command Verification condition assert E; assume E; nowarn Automatic theorem prover Counterexample context Post processor Warning messages assume x >= 0; // because x == y*y x = a[j]; //@ nowarn axiom E; axiom (\forall int x; x >> 2 >= 0); Weakest preconditions Annotated Java program Translator Sugared command Primitive command Passive command 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 Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Verification condition Annotated Java program Translator Sugared command Universal background predicate Primitive command Passive command (FORALL (t) (<: t t)) Type-specific background predicate (<: T_T |T_java.lang.Object|) Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Verification condition: BPUniv BPT VCmethod Verification condition generation Easy for small languages [Dijkstra] Much harder for real languages Object-oriented Typed Dynamic allocation Exceptions Aliasing Threads Verification conditions for real programs Java Guarded command wlp Verification condition x = a[ i++ ]; assume preconditions assume invariants ... i0 = i; i = i + 1; assert (LABEL Null@218: a != null); assert (LABEL IndexNeg@218: 0 <= i0); assert (LABEL IndexTooBig@218: i0 < a.length); x = elems[a][i0]; ... assert postconditions assert invariants i0.(i0 == i ==> … ) Verification condition Formula in untyped, first-order predicate calculus equality and function symbols quantifiers arithmetic operations select and store operations Eg. x.y.(x > y ==> … ) Background axioms Additional properties of Java that the theorem prover needs to know A variable of type T always holds a value whose type is a subtype of T The subtyping relation is reflexive, anti-symmetric, and transitive new returns an object that is distinct from all existing objects ... lots more ... java.lang.Object has no supertype Example verification condition Verification condition large but “dumb” (IMPLIES (DISTINCT |ecReturn| |L_14.4|) (IMPLIES (AND (EQ |a@pre:2.8| |a:2.8|) (EQ |a:2.8| (asField |a:2.8| (array |T_int|))) (< (fClosedTime |a:2.8|) alloc) (EQ |n@pre:3.6| |n:3.6|) (EQ |n:3.6| (asField |n:3.6| |T_int|)) (EQ |MAX_VALUE@pre:3.4.26| |MAX_VALUE:3.4.26|) (EQ |@true| (is |MAX_VALUE:3.4.26| |T_int|)) (EQ |elems@pre| elems) (EQ elems (asElems elems)) (< (eClosedTime elems) alloc) (EQ LS (asLockSet LS)) (EQ |alloc@pre| alloc) (EQ |@true| (is |this<1>| |T_Bag|)) (EQ |@true| (isAllocated |this<1>| alloc)) (NEQ |this<1>| null)) (FORALL (tmp1 |tmp2:21.4| |tmp3:21.6| |m:12.8| |mindex:13.8| |i:14.13| |tmp0:14.28|) (AND (IMPLIES (<= 1 (select |n:3.6| |this<1>|)) (AND (LBLNEG |[email protected]~15.10| (NEQ (select |a:2.8| |this<1>|) null)) (LBLNEG |[email protected]~15.11| (<= 0 1)) (LBLNEG |[email protected]~15.11| (< 1 (arrayLength (select |a:2.8| |this<1>|)))) (IMPLIES (< (select (select elems (select |a:2.8| |this<1>|)) 1) |MAX_VALUE:3.4.26|) (AND (LBLNEG |[email protected]~17.12| (NEQ (select |a:2.8| |this<1>|) null)) (LBLNEG |[email protected]~17.13| (<= 0 1)) (LBLNEG |[email protected]~17.13| (< 1 (arrayLength (select |a:2.8| |this<1>|)))) (FORALL (|m:17.8|) (IMPLIES (EQ |m:17.8| (select (select elems (select |a:2.8| |this<1>|)) 1)) (FORALL (|i:14.28|) (IMPLIES (AND (EQ |i:14.28| (+ 1 1)) (EQ |@true| |bool$fals e|)) (FORALL (|tmp2:21.4<1>|) (IMPLIES (EQ |tmp2:21.4<1>| (select |a:2.8| |this<1>|)) (AND (LBLNEG |[email protected]~21.16| (NEQ (select |a:2.8| |this<1>|) null)) (LBLNEG |[email protected]~21.17| (<= 0 (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|))) (LBLNEG |[email protected]~21.17| (< (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|) (arrayLength (select |a:2.8| |this<1>|)))) (LBLNEG |[email protected]~21.4| (NEQ |tmp2:21.4<1>| null)) (LBLNEG |[email protected]~21.5| (<= 0 1)) (LBLNEG |[email protected]~21.5| (< 1 (arrayLength |tmp2:21.4<1>|))) (LBLNEG |Exception:[email protected]~11.2| (EQ |ecReturn| |ecReturn|))))))))))) (IMPLIES (NOT (< (select (select elems (select |a:2.8| |this<1>|)) 1) |MAX_VALUE:3.4.26|)) (FORALL (|i:14.28|) (IMPLIES (AND (EQ |i:14.28| (+ 1 1)) (EQ |@true| |bool$false|)) (FORA LL (|tmp2:21.4<1>|) (IMPLIES (EQ |tmp2:21.4<1>| (select |a:2.8| |this<1>|)) (AND (LBLNEG |[email protected]~21.16| (NEQ (select |a:2.8| |this<1>|) null)) (LBLNEG |[email protected]~21.17| (<= 0 (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|))) (LBLNEG |[email protected]~21.17| (< (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|) (arrayLength (select |a:2.8| |this<1>|)))) (LBLNEG |[email protected]~21.4| (NEQ |tmp2:21.4<1>| null)) (LBLNEG |[email protected]~21 .5| (<= 0 0)) (LBLNEG |[email protected]~21.5| (< 0 (arrayLength |tmp2:21.4<1>|))) (LBLNEG |Exception:[email protected]~11.2| (EQ |ecReturn| |ecReturn|)))))))))) (IMPLIES (NOT (<= 1 (select |n:3.6| |this<1>|))) (AND (IMPLIES (EQ |L_14.4| |L_14.4|) (FORALL (|tmp2:21.4<1>|) (IMPLIES (EQ |tmp2:21.4<1>| (select |a:2.8| |this<1>|)) (AND (LBLNEG |[email protected]~21.16| (NEQ (select |a:2.8| |this<1>|) null)) (LBLNEG |[email protected]~21.17| (<= 0 (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|))) (LBLNEG |[email protected]~21.17| (< (select (store |n:3.6| |this<1>| ( - (select |n:3.6| |this<1>|) 1)) |this<1>|) (arrayLength (select |a:2.8| |this<1>|)))) (LBLNEG |[email protected]~21.4| (NEQ |tmp2:21.4<1>| null)) (LBLNEG |[email protected]~21 .5| (<= 0 0)) (LBLNEG |[email protected]~21.5| (< 0 (arrayLength |tmp2:21.4<1>|))) (LBLNEG |Exception:[email protected]~11.2| (EQ |ecReturn| |ecReturn|)))))) (IMPLIES (NOT (EQ |L_14.4| |L_14.4|)) (AND (LBLNEG |Exception:[email protected]~11.2| (EQ |L_14.4| |ecReturn|)))))))))) Annotated Java program Translator Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages (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|)) Verification condition class T { static int abs(int x) { if (x < 0) { x = -x; } //@ assert x >= 0; } } Annotated Java program Translator Sugared command Theorem prover: “Simplify” Nelson-Oppen cooperating decision procedures Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Key features: Post processor Warning messages congruence closure linear arithmetic partial orders quantifiers automatic: no user interaction refutation based: searches for counterexamples heuristics tuned for program checking labels time limit Automatic theorem proving Verification condition x.y.(x > y ==> … ) Automatic theorem prover (Simplify) Valid Counterexample Diverges Counterexamples and warnings Annotated Java program Translator Sugared command Primitive command Passive command Verification condition Automatic theorem prover Counterexample context Post processor Warning messages Counterexample: labels: (|[email protected]| |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. ------------------------------------------------------------------------ ESC/Java research platform Annotation inference Other checking tools Calvin [Qadeer et al.], Stale-value concurrency checker [Burrows & Leino] Formal verification without driving theorem prover Simplify theorem prover Daikon [Ernst], Houdini [Flanagan & Leino] SLAM [Ball, Rajamani, et al.], oolong [Leino et al.], … Teaching Kansas State University [Dwyer & Hatcliff]