Extended Static Checking with ESC/Java2 1. Overview Wolfgang Schreiner Wolfgang.Schreiner@risc.uni-linz.ac.at 2. Examples Research Institute for Symbolic Computation (RISC) Johannes Kepler University, Linz, Austria http://www.risc.uni-linz.ac.at 3. Handling of Loops 4. Internal Operation Wolfgang Schreiner http://www.risc.uni-linz.ac.at 1/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 2/47 ESC/Java2 Theoretical Limitations Latest outcome of a series of projects. ESC/Java2 is not sound. Soundness: if { P } c { Q } does not hold, it cannot be proved. Compaq: ESC/Modula-3 (–1996), ESC/Java (–2000). Univ. Nijmegen (–2005), Univ. College Dublin (2005–): ESC/Java2. ESC/Java2 may not produce warning on wrong { P } c { Q } . http://secure.ucd.ie/products/opensource/ESCJava2 Sources of unsoundness: Extended Static Checking for Java. Loops are handled by unrolling, arithmetic is on Z . JML annotation assume adds unverified knowledge. Find programming errors by automated reasoning techniques. Object invariants are not verified on all existing objects. Simplified variant of Hoare/weakest precondition calculus. ESC/Java2 is not complete. Full Java 1.4, fully automatic. Completeness: if { P } c { Q } cannot be proved, it does not hold. Feels like type-checking. ESC/Java2 may produce superfluous warnings. Uses JML for specification annotations (ESC/Java2). Sources of incompleteness: ESC/Modula-3 and ESC/Java had their own annotation language. Simplify’s limited reasononing capabilities (arithmetic, quantifiers). Based on the Simplify prover. JML annotation nowarn to turn off warnings. Greg Nelson et al, written in Modula-3 for ESC/Modula-3. Potentially not sound. Finding errors in a program rather than verifying it. Not every error is detected, not every warning actually denotes an error. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 3/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 4/47
Practical Usefulness ESC/Java2 detects many (most) programming errors. Array index bound violations. 1. Overview Division by zero. Null-pointer dereferences. Violation of properties depending on linear arithmetic. 2. Examples . . . Forces programmer to write method contracts. Especially method preconditions. 3. Handling of Loops Better documented and better maintainable code. A useful extension of compiler type checking. 4. Internal Operation Wolfgang Schreiner http://www.risc.uni-linz.ac.at 5/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 6/47 Use of ESC/Java2 Tutorial Program class Bag { Command-line interface. int[] a; int n; escjava2 [ options ] File .java Bag(int[] input) { n = input.length; a = new int[n]; Graphical interface. System.arraycopy(input, 0, a, 0, n); } java -jar esctools2.jar int extractMin() { escjava2 -help . int m = Integer.MAX_VALUE; int mindex = 0; for (int i = 1; i <= n; i++) { if (a[i] < m) { mindex = i; m = a[i]; } } n--; a[mindex] = a[n]; return m; } } Wolfgang Schreiner http://www.risc.uni-linz.ac.at 7/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 8/47
Tutorial Program: Assumptions Tutorial Program: Guarantees class Bag { /*@ requires n>0; /*@ non_null @*/ int[] a; @ ensures n == \old(n)-1; int n; /*@ invariant 0 <= n && n <= a.length; @*/ @ ensures (\forall int i; 0 <= i && i < \old(n); @ \result <= \old(a[i])); /*@ requires input != null; @*/ @*/ Bag(int[] input) { int extractMin() { ... ... } } Postconditions may be added (and are checked to some extent). /*@ requires n>0; @*/ int extractMin() { ... } Invariants and preconditions have to be added to pass the checking. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 9/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 10/47 Tutorial Program: Wrong Guarantees Example Program: Arithmetic1 /*@ requires n>0; //@ ensures \result == i; @ ensures n == \old(n)-1; static int f2(int i) @ ensures (\forall int i; 0 <= i && i < \old(n); { @ \result <= \old(a[i])); @*/ int j = i+1; int extractMin() { int k = 3*j; int m = Integer.MAX_VALUE; return k-2*i-3; int mindex = 0; for (int i = 0; i < n; i++) { } if (a[i] < m) { mindex = i; //@ requires i < j; m = a[0]; // ERROR: a[0] rather than a[i] //@ ensures \result >= 1; } static int f4(int i, int j) } { n--; a[mindex] = a[n]; return 2*j-2*i-1; return m; } } Masters linear integer arithmetic with inequalities. But also this program passes the check! Wolfgang Schreiner http://www.risc.uni-linz.ac.at 11/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 12/47
Example Program: Sort Example Program: Conditional /*@ requires a != null; /*@ ensures (\result == i || \result == j || \result == k) @ ensures (\forall int i; 0 <= i && i < a.length-1; a[i] <= a[i+1]); @ && (\result <= i && \result <= j && \result <= k); @*/ @*/ static int min(int i, int j, int k) static void insertSort(int[] a) { { int m = i; int n = a.length; if (j < m) m = j; for (int i = 1; i < n; i++) { if (k < m) m = k; int x = a[i]; return m; int j = i-1; } while (j >= 0 && a[j] > x) { a[j+1] = a[j]; Masters conditionals. j = j-1; } a[j+1] = x; } } Detects many errors in array-based programs. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 13/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 14/47 Example Program: Arithmetic2 Example Program: Loop //@ ensures \result == i*i; //@requires n >= 0; static int f1(int i) static void loop(final int n) { { return i*(i+1)-i; int i=0; } //@ nowarn Post; while (i < n) { //@ ensures \result >= 0; i = i+1; static int f2(int i) } { //@ assert i==n; return i*i; //@ assert i<3; } //@ nowarn Post; } Does not master non-linear arithmetic. Does only partially master post-conditions of programs with loops. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 15/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 16/47
Loop Unrolling We will now use a high-level description of the ESC/Java2 handling of loops by loop unrolling. 1. Overview Original program. while ( e ) c ; 2. Examples Unrolling the loop once. if ( e ) { c ; while ( e ) c ; } Unrolling the loop twice. 3. Handling of Loops if ( e ) { c ; if ( e ) { c ; while ( e ) c ; } } Faithful loop unrolling preserves the meaning of a program. 4. Internal Operation Wolfgang Schreiner http://www.risc.uni-linz.ac.at 17/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 18/47 Verification of Unrolled Program ESC/Java2 Loop Unrolling Faithful unrolling Let us consider how verification is affected by loop unrolling. { P } if( e ) { c ; if( e ) { c ; while ( e ) c }} { Q } Original: { P } while( e ) c { Q } ESC/Java2 default unrolling P ⇒ wp(while( e ) c , Q ) (0) { P } if( e ) { c ; if( e ) { assume false; }} { Q } Unrolled: { P } if ( e ) { c ; if ( e ) { c ; while ( e ) c }} { Q } Not unrolled execution of loop is replaced by “ assume false”. ( P ∧ ¬ e ) ⇒ Q (1) assume false: from false, everything can be concluded. { P ∧ e } c ; if ( e ) { c ; while ( e ) c } { Q } No more verification takes place in this branch. { P ∧ e } c {¬ e ⇒ Q } (2) { P ∧ e } c { e ⇒ wp( c ; while ( e ) c , Q ) } (3) Only simplified program is verified by ESC/Java2. Three obligations (1-3) equivalent to original obligation (0). Wolfgang Schreiner http://www.risc.uni-linz.ac.at 19/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 20/47
Verification of Unrolled Program Expressive Power of Simplified Verification Checked proof obligations Let us consider the simplified verification problem. ( P ∧ ¬ e ) ⇒ Q { P } if( e ) { c ; if( e ) { assume false }} { Q } Postcondition holds, if loop terminates after zero iterations. ( P ∧ ¬ e ) ⇒ Q (1) { P ∧ ¬ e } c {¬ e ⇒ Q } { P ∧ e } c ; if( e ) { assume false }} { Q } Postcondition holds, if loop terminates after one iteration. { P ∧ e } c {¬ e ⇒ Q } (2) Unchecked proof obligation { P ∧ e } c { e ∧ false ⇒ Q } { P ∧ e } c { e ⇒ wp( c ; while ( e ) c , Q ) } ⇔ { P ∧ e } c { true } ⇔ true Postcondition holds, if loop terminates after more than one iteration. Proof obligation (3) of the original problem is dropped. Only partial verification of loops in ESC/Java 2. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 21/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 22/47 Expressive Power of Simplified Verification Control of Loop Unrolling ESC/Java2 control of loop unrolling What does this mean for the whole verification process? escjava2 -loop n .5 Example program: Loop is unrolled n times (default n = 1). while ( e ) { c 1 } c 2 .5: also loop condition after n -th unrolling is checked. Verified program: Preconditions. if ( e ) { c 1 ; if ( e ) { assume false } } c 2 if ( e ) { c 1 ; if ( e ) { assume false } c 2 } else c 2 All preconditions are checked that arise from the loop expression and if ( e ) { c 1 ; if ( e ) { assume false; c 2 } else c 2 } else c 2 the loop body in the first n iterations. if ( e ) { c 1 ; if ( e ) skip else c 2 } else c 2 Postconditions. if ( e ) { c 1 ; if ( ¬ e ) c 2 } else c 2 It is checked whether the postcondition of the loop holds in all In verified program, only runs are considered where executions that require at most n iterations. loop terminates after at most one iteration, i.e. All program paths with more than n iterations are “cut off”. execution of c 2 is only considered in such program runs. After a loop, only special contexts are considered for verification. Wolfgang Schreiner http://www.risc.uni-linz.ac.at 23/47 Wolfgang Schreiner http://www.risc.uni-linz.ac.at 24/47
Recommend
More recommend