Presentation is loading. Please wait.

Presentation is loading. Please wait.

Automatic Discovery of Software Contract Work in progress Yishai Feldman, Leon Gendler.

Similar presentations


Presentation on theme: "Automatic Discovery of Software Contract Work in progress Yishai Feldman, Leon Gendler."— Presentation transcript:

1 Automatic Discovery of Software Contract Work in progress Yishai Feldman, Leon Gendler

2 Design By Contract Precondition An obligation of the consumer (client) A set of assertions to be ensured before executing a program part Postcondition An obligation of the provider (server) A set of conditions to be fulfilled after executing a program part Invariant A set of conditions concerning the state of the class Ensured to hold before and after each class operation.

3 Design By Contract Reliability Avoid unexpected inputs and results Expresses and validates correctness arguments Make sure you know what your code does Testing Contract violation means a bug Documentation Express the input and outcome of each class method

4 Contract A set of pre- and post conditions for each operation provided by a component and an invariant for the whole class. Ensuring the precondition when requesting an operation, guarantees the provider will make the postcondition true at its end.

5 Contract Example /** @inv (top >= 0 && top = 0 && top < max)*/ /** @pre (sz > 0) @post (max == sz && elems != null) */ class Stack { private Object[] elems; private int top, max; /** @pre (sz > 0) @post (max == sz && elems != null) */ public MyStack(int sz) { max = sz; elems = new Object[sz]; } /** @pre !isFull() @post (top == $prev (top) + 1) && elems[top-1] == obj */ /** @pre !isFull() @post (top == $prev (top) + 1) && elems[top-1] == obj */ public void push(Object obj) { elems[top++] = obj; } /** @pre !isEmpty() @post (top == $prev (top) - 1) && $ret == elems[top] */ /** @pre !isEmpty() @post (top == $prev (top) - 1) && $ret == elems[top] */ public Object pop() { return elems[--top]; } /** @post ($ret == (top == max)) */ /** @post ($ret == (top == max)) */ public boolean isFull() { return top == max; } /** @post ($ret == (top == 0)) */ /** @post ($ret == (top == 0)) */ public boolean isEmpty() { return top == 0; } }

6 Research Purpose To find a proper contract for a given class by performing static program analysis. The contract may not be complete, there may be pre/post conditions that will not be found The contract will (?) be correct. Discover from the code itself the conditions for its correctness (preconditions) No intention to verify the correctness of a given piece of code. Describe the code’s outcome and the claims about the object’s state at end of execution (postconditions).

7 Example public synchronized boolean addAll(int index, Collection c) { if (index elementCount) throw new ArrayIndexOutOfBoundsException(index); int numNew = c.size(); ensureCapacityHelper(elementCount + numNew); int numMoved = elementCount - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); Iterator e = c.iterator(); for (int i = 0; i < numNew; i++) elementData[index++] = e.next(); elementCount += numNew; return numNew != 0; } // @inv: elementData != null // @inv: elementCount <= elementData.length() // @post: elementData.length() <= $pre(elementCount) + c.size() // @post: forall i, 0 <= i < c.size(): // $prev(elementData[index + i] = //elementData[index + i + c.size()] // @pre: index >= 0 // @pre: index <= elementCount // @pre: c != null

8 Verification Condition A logical expression representing a program part. Proving the VC to be correct, proves the program part to be correct. Program verification: Annotate program with assertions and loop invariants (manually). Build all VCs by traversing the annotated program. If the VC is correct then the program stands correct according to the given assertions.

9 Mechanizing Program Verification Specification to be proved + Loop Invariants Human expert Annotated specification VC Generator Set of logic statements (VC’s) Theorem Prover Simplified set of verif. cond. End of proof Human Expert

10 Hoare Triplets {P} S {Q} - Starting at state {P} and performing S will bring us to state {Q} Weakest Precondition: wp(S, Q): The weakest initial state {P} in which after performing S will bring us to state {Q} WLP(S, Q): Doesn’t ensure termination Strongest Postcondition SP(S, P): The strongest state {Q} which can be achieved starting at {P} and performing S

11 Weakest? Strongest? A is stronger than B:A  B A is weaker than B:B  A The weakest condition: True The strongest condition:False

12 The stronger {P} means less cases to handle, easier job for S {False} S {…}: The easiest job - The customer is always wrong, we can do whatever we want. We need to ask S to work with the weakest {P} The least restriction on the input The Stronger {Q} means more results {…} S {True}: Second Best - We can do whatever we want, but must terminate We expect S to reach the strongest {Q} The maximum the operation can achieve {P} S {Q}: Weakest? Strongest?

13 Precondition Computation Use Weakest Precondition method to calculate preconditions. Start with the weakest condition : True Traverse the code bottom-up and push the condition through all program instructions. Each command can add to the precondition.

14 Weakest Precondition wp(x := e, Post) = Post(x := e) Every free occurrence of x in postcondition P is replaced by e. wp(S1;S2, Post) = wp(S1, wp(S2, Post)) Calculate the WP bottom up wp(if B then S1 else S2, Post) = B  wp(S1, Post)   B  wp(S2, Post) wp(while B do S1, Post) =  B  Post  B  wp(while B do S1, wp(S1, Post)) L(i) =  B  Post  B  wp(L(i-1))

15 Automatic Discovery of Software Contracts Translate the source code into a structural representation (the Plan Calculus). Use a library of structural elements and their contract (assertions) to assign to each structural element its pre/post conditions. Propagate the assertions upwards and downwards through the plan to produce the preconditions and the postconditions. (V.C. generation) Add knowledge by applying heuristics of frequent code Simplify expressions

16 Looking for a contract Practical Something the programmer can work with A starting point for the programmer to check for possible bugs. Must contain relevant data No local method variables Class members and input variables Must be correct, but ‘almost’ also counts Completeness is impossible

17 Implementation Input: a Java class source code Translate the Java class into a plan representation Code written in Java using Barat Barat: A front-end for Java to support static analysis of Java programs. Builds a complete abstract syntax tree from Java source code files, enriched with name and type analysis information. Generate a Lisp representation of a plan. Traverse the plan generating the contract. Use predefined spec’s assertion and known methods’ library Use ACL2 Theorem Prover to simplify generated logical expressions and to check possible contract assumptions.

18 ACL2 An automated reasoning system Developed (for the first 9 years) at Computational Logic, Inc. and (from January, 1997) at the University of Texas at Austin. The successor to the Nqthm (or Boyer-Moore) logic and proof system A Computational Logic for Applicative Common Lisp An automated theorem prover or proof checker A competent user can utilize the ACL2 system to discover proofs of theorems stated in the ACL2 logic or to check previously discovered proofs

19 WP Example {(and (>= i 0) (< i 5))} int j = i * 2; {(and (not (eq a nil)) (>= i 0) (< i (len a)))} a[i] = j; {t} int [] a = new int [5]; {(let ((j (* 2 i))) (and (not (eq a nil)) (>= i 0) (< i (len a)))} {(and (not (eq a nil)) (>= i 0) (< i (len a))), (not (eq a nil)) (eq (len a) 5))} {(and (>= 5 0) (>= i 0) (< i 5))} int foo (int i) { int [] a = new int[5]; int j = i*2; a[i] = j;... }

20 Plan Calculus A structural, high level representation Manipulation of local variables is represented as Data Flow Representation of Control Flow which can be parallel. Spec Types: IO Spec Test Spec Join Spec

21 Condition Structure Outer Failure Success Outer-wp Join Test Success-wp Failure-wp  Test  Failure-wp  Test  Success-wp

22 negate-if-negative < Join FS Test FS int abs (int x) { If (x < 0) { x = -x; } return x; } - x

23 Loops Traverse the loop several times until: Either a fixed-point in the contract is reached Or a fixed number of iteration Usually, the first traversal contributes most of the information. Try to identify special behavior: well-known loop structures such as array or range iteration.

24 Loop structure feedback body outer Body-wp Feedback-wpOuter-wp Join Test

25 For example Test FS Join FS < aset ++ i i i i i = init limit for (i=init; i<limit; i++) {... a[i] = x... } a a a a x

26 Vector.addAll(int, collection) public synchronized boolean addAll(int index, Collection c) { if (index elementCount) throw new ArrayIndexOutOfBoundsException(index); int numNew = c.size(); ensureCapacityHelper(elementCount + numNew); int numMoved = elementCount - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); Iterator e = c.iterator(); int limit = index + numNew; for (int i = index; i < limit; i++) elementData[i] = e.next(); elementCount += numNew; return numNew != 0; }

27 Precondition of Vector.addAll(int, collection) (AND (NOT (OR (< INDEX 0) (< ELEMENTCOUNT INDEX))) C (OR (NOT (< 0 (+ ELEMENTCOUNT (- INDEX)))) (AND (NOT (< (+ INDEX NUMNEW) 0)) ELEMENTDATA (<= (+ INDEX ELEMENTCOUNT (- INDEX)) (LEN ELEMENTDATA)) (<= (+ INDEX NUMNEW ELEMENTCOUNT (- INDEX)) (LEN ELEMENTDATA)))))... (AND (>= INDEX 0) (>= ELEMENTCOUNT INDEX) ;; If (…) Throw {…} C;; c.size() (IMPLIES ( 0)… (AND (>= (+ INDEX NUMNEW) 0) ;; System.arrayCopy ELEMENTDATA (<= ELEMENTCOUNT (LEN ELEMENTDATA)) (<= (+ NUMNEW ELEMENTCOUNT) (LEN ELEMENTDATA)))))

28 Precondition of Vector.addAll(int, collection) (AND (>= INDEX 0) (>= ELEMENTCOUNT INDEX) C (IMPLIES (< 0 (- ELEMENTCOUNT INDEX)) (AND (>= (+ INDEX NUMNEW) 0) ELEMENTDATA (<= ELEMENTCOUNT (LEN ELEMENTDATA)) (<= ELEMENTCOUNT (LEN ELEMENTDATA)) (<= (+ NUMNEW ELEMENTCOUNT) (LEN ELEMENTDATA))) (<= (+ NUMNEW ELEMENTCOUNT) (LEN ELEMENTDATA))))) Class Invariant Postcondition of ensureCapacityHelper(int capacity): (LEN ELEMENTDATA) >= capacity

29 Full Precondition (AND (NOT (OR (< INDEX 0) (< ELEMENTCOUNT INDEX))) C (OR (NOT (< 0 (+ ELEMENTCOUNT (- INDEX)))) (AND (NOT (< (+ INDEX NUMNEW) 0)) ELEMENTDATA (<= (+ INDEX ELEMENTCOUNT (- INDEX)) (LEN ELEMENTDATA)) (<= (+ INDEX NUMNEW ELEMENTCOUNT (- INDEX)) (LEN ELEMENTDATA)) (OR (NOT (< INDEX LIMIT)) (AND E (< 0 INDEX) (AND E (< 0 INDEX) (< INDEX (LEN ELEMENTDATA)) (< INDEX (LEN ELEMENTDATA)) (OR (NOT (< (+ 1 INDEX) LIMIT)) (OR (NOT (< (+ 1 INDEX) LIMIT)) (< (+ 1 INDEX) (LEN ELEMENTDATA))))) )) (< (+ 1 INDEX) (LEN ELEMENTDATA))))) )) (COND ((< 0 (+ ELEMENTCOUNT (- INDEX))) T) ((< INDEX LIMIT) (AND E ELEMENTDATA (< 0 INDEX) (< INDEX (LEN ELEMENTDATA)) (OR (NOT (< (+ 1 INDEX) LIMIT)) (< (+ 1 INDEX) (LEN ELEMENTDATA))))) (T T)))

30 Cleaning the result The precondition may contain irrelevant data internal implementation The precondition should contain only global and input variables.

31 Adding more knowledge Serial traversal: Most commonly used loop to traverse an array (any serial traversal) Adding the calculation of the last loop traversal Add special information: For (i = init; i < limit; i++) {... NO BREAK...}: Assert init < limit  "First execution"  i=limit  #=limit-init Assert  (init < limit)  "No execution"  i = init  # = 0

32 Serial Traversal for(i = init; i < limit; i++) { … a[i] = … } Easy to find: 0  init < a.len Better: a.length()  limit Method: Add i = limit (the last value of i) as a postcondition of the loop. Compute the loop precondition based on: L(k) - the postcondition computed so far i = limit - the value of i on the last iteration

33 for(i=0; i<n; i++) {… a[i] …} L(0) = outer, L(i) =  p  L(0)  p  wp(S,L(i-1)) L(1) = i  n  outer  i<n  wp(…a[i]…, wp(i++, L(0))) L(1) = i  n  outer  i < n  0  i < a.len L(2) = i  n  outer  i<n  wp(…a[i]…;i++, L(1)) L(2) = i  n  outer  i<n  wp(…a[i]…;i++, i  n  outer  i < n  0  i < a.len) L(2) = i  n  outer  i = n-1  wp(outer)  i < n  0  i < a.len  i+1 < n  0  i+1 < a.len L(k) = i  n  outer  […  i=n-k  wp k-1 (outer)  …]  [i < n  0  i < a.len)  … i+k < n  0  i+k-1 < a.len)]

34 Wp(loop, i=0) 0 < n  0  0 < a.len 1 < n  0  1 < a.len … k < n  0  k < a.len wp(…a[i];i++…, L(k)  i = n)) (after loop exit)  wp(…a[i];i++…, wp(i++, L(k)  i = n))  wp(…a[i], L(k) i = i+1  i+1 = n  0  i < a.len  L(k) i = i+1  i+1 = n  0  n-1 < a.len  L(k) i = i+1

35 Computing Postconditions Similar computation as in Preconditions. Possible improvement: use the already computed preconditions as an initial value

36 Class Invariant Finding candidates: Assertions regarding class members Assertions appearing in more that one method’s preconditions. Assertions appearing in pre and post conditions Checking candidate assertions: The assertion doesn’t effect contract of methods it is not part of their contract.

37 Related Research ESC/Java Statically detects common errors such as null pointer references Programmer adds annotations (assertion statements) ESC/Java issues warnings about annotations which cannot be verified. Translates the program into V.C.s and tries to prove them. Houdini Guesses a candidate set of annotations and uses ESC/Java to prove them correct

38 Block diagram

39 ESC example class Bag { int[] a; int n; Bag(int[] input) { n = input.length; a = new int[n]; System.arraycopy(input, 0, a, 0, n); } 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]; } n--; a[mindex] = a[n]; return m; }

40 escjava Bag.java

41 ESC example class Bag { /*@ non_null */ int[] a; int n; //@ invariant 0 <= n && n <= a.length; //@ requires input != null; Bag(int[] input) { n = input.length; a = new int[n]; System.arraycopy(input, 0, a, 0, n); } //@ requires n >= 1; 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]; } n--; a[mindex] = a[n]; return m; }

42 Blow-up from assignment rule wp(x := e,Q) = Q(x  e) Q(x  e) may contain many copies of e Sequential composition of assignment statements may yield exponentially large VC, e.g. wp( b=a+a ; c=b+b ;... ; z=y+y, z>0)

43 References Bertrand Meyer, Object-Oriented Software Construction, 2nd edition, Prentice-Hall, 1997. Charles Rich, Richard C. Waters, The Programmer's Apprentice, Addison-Wesley, November 1990. Matt Kaufmann, Panagiotis Manolios, and J Strother Moore, Computer-Aided Reasoning: An Approach, Kluwer Academic Publishers, June, 2000 Edsger W. Dijkstra, Carel S. Scholten Predicate Calculus and Program Semantics, Springer-Verlag, July 1989. Richard C. Waters, "A Method for Analyzing Loop Programs", IEEE Transactions on Software Engineering, vol. 5 pp. 237-247, May 1979. Guy L. Steele Jr., Common Lisp: The Language, 2nd edition, Butterworth- Heinemann, December 1990. David L. Detlefs, K. Rustan M. Leino, Greg Nelson, and James B. Saxe. "Extended Static Checking". Research Report 159, Compaq Systems Research Center, December, 1998.


Download ppt "Automatic Discovery of Software Contract Work in progress Yishai Feldman, Leon Gendler."

Similar presentations


Ads by Google