1 / 53

Efficient Software Model Checking of Soundness of Type Systems

Efficient Software Model Checking of Soundness of Type Systems. Michael Roberson, Melanie Harries, Paul T. Darga, Chandrasekhar Boyapati University of Michigan. Type Soundness. All Possible Programs defined by the syntax. Good Programs do not cause certain kinds of runtime errors

usoa
Download Presentation

Efficient Software Model Checking of Soundness of Type Systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Efficient Software Model Checking of Soundness of Type Systems Michael Roberson, Melanie Harries, Paul T. Darga, Chandrasekhar Boyapati University of Michigan

  2. Type Soundness • All Possible Programs • defined by the syntax • Good Programs • do not cause certain kinds of runtime errors • e.g. memory errors, race conditions, etc. • defined by the semantics

  3. Type Soundness • Type System • designed to statically prevent errors • must accept only good programs • Well Typed Programs • defined by the type system

  4. Type Soundness • Type Soundness • well typedimpliesgood • entire class of errors eliminated at compile time

  5. Type Soundness • Much research in new type systems • Proving type soundness is important • Becoming its own research area • POPLmark workshop • Proving type soundness is tedious • Manual proofs • Machine checked proofs • Both require intensive human effort • Our technique is completely automatic • Our technique provides counterexamples

  6. Outline • Motivation • Example • Approach • Experimental Results • Related Work • Conclusions

  7. Example Syntax: e :== true | false | 0 | succe | prede | iszeroe | ife1thene2elsee3 Semantics: Final States: v :== true | false | nv nv :== 0 | succnv Bad program: iszero true Good program: iszero 0

  8. Example Type system: T :== Nat|Bool Typing rules: Type soundness: Every well typed program is a good program.

  9. Soundness Proof • Parts to a Soundness Proof: • Progress Theorem • If wellTyped(t) then t is a final state or t transitions to t’ • Preservation Theorem • If wellTyped(t) and t transitions to t’ then wellTyped(t’) • Together, these two theorems imply Type Soundness

  10. Software Model Checking • Software Model Checking • For each well typed program state • Check Progress • Check Preservation • If a check fails, show a counterexample

  11. Challenges • Search space is infinite! • Impose finite bounds on the search space • Small Scope Hypothesis justifies this approach • [Jackson96][Offutt00][Marinov03] • Search space is huge! • Find similarities and eliminate redundancy

  12. State Space Reduction • Many software model checkers • Verisoft, JPF, CMC, SLAM, Blast, Magic, … • Many state space reduction techniques • Partial order reduction • Predicate abstraction • Not effective for checking type soundness

  13. if if if iszero false iszero succ iszero false true pred if 0 0 0 0 0 false true false if if if true false true succ true false true pred if 0 0 false true false Our Key Idea if iszero 0 then true else false PRUNED

  14. Outline • Motivation • Example • Approach • Defining the language • Searching the state space • Representing the state space • Reducing the state space • Experimental Results • Related Work • Conclusions

  15. Language Definition classExpressionLanguageimplementsLanguage { … static classExpression { intkind; // TRUE, FALSE, ZERO, SUCC, PRED, ISZERO, IF @TreeExpression e1, e2, e3; @DeclarativebooleanwellTyped() { returnsyntaxOk() && (kind == TRUE ==>true ) && (kind == FALSE ==>true ) && (kind == ZERO ==>true ) && (kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && (kind == PRED ==> e1.wellTyped() && e1.type() == INT) && (kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && (kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type()); } Expression smallStep()throwsStuckException { if(isValue())returnthis; if(!e1.isValue()) { e1 = e1.smallStep();returnthis; } if(kind == PRED && e1.kind == ZERO )returne1; if(kind == PRED && e1.kind == SUCC )returne1.e1; if(kind == ISZERO && e1.kind == ZERO )returnTrue(); if(kind == ISZERO && e1.kind == SUCC )returnFalse(); if(kind == IF && e1.kind == TRUE )returne2; if(kind == IF && e1.kind == FALSE)returne3; thrownewStuckException(); } // Helper Functions … } Expression root; @DeclarativepublicbooleanwellTyped() {returnroot.wellTyped(); } publicvoidsmallStep()throwsStuckException { root = root.smallStep(); } publicbooleanisFinalState() {returnroot.isValue(); } }

  16. Language Definition classExpressionLanguageimplementsLanguage { … static classExpression { intkind; // TRUE, FALSE, ZERO, SUCC, PRED, ISZERO, IF @TreeExpression e1, e2, e3; @DeclarativebooleanwellTyped() { returnsyntaxOk() && (kind == TRUE ==>true ) && (kind == FALSE ==>true ) && (kind == ZERO ==>true ) && (kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && (kind == PRED ==> e1.wellTyped() && e1.type() == INT) && (kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && (kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type()); } Expression smallStep()throwsStuckException { if(isValue())returnthis; if(!e1.isValue()) { e1 = e1.smallStep();returnthis; } if(kind == PRED && e1.kind == ZERO )returne1; if(kind == PRED && e1.kind == SUCC )returne1.e1; if(kind == ISZERO && e1.kind == ZERO )returnTrue(); if(kind == ISZERO && e1.kind == SUCC )returnFalse(); if(kind == IF && e1.kind == TRUE )returne2; if(kind == IF && e1.kind == FALSE)returne3; thrownewStuckException(); } // Helper Functions … } Expression root; @DeclarativepublicbooleanwellTyped() {returnroot.wellTyped(); } publicvoidsmallStep()throwsStuckException { root = root.smallStep(); } publicbooleanisFinalState() {returnroot.isValue(); } } staticclassExpression { intkind; // TRUE, FALSE, ZERO, SUCC, PRED, ISZERO, IF @TreeExpression e1, e2, e3; … }

  17. Language Definition classExpressionLanguageimplementsLanguage { … static classExpression { intkind; // TRUE, FALSE, ZERO, SUCC, PRED, ISZERO, IF @TreeExpression e1, e2, e3; @DeclarativebooleanwellTyped() { returnsyntaxOk() && (kind == TRUE ==>true ) && (kind == FALSE ==>true ) && (kind == ZERO ==>true ) && (kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && (kind == PRED ==> e1.wellTyped() && e1.type() == INT) && (kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && (kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type()); } Expression smallStep()throwsStuckException { if(isValue())returnthis; if(!e1.isValue()) { e1 = e1.smallStep();returnthis; } if(kind == PRED && e1.kind == ZERO )returne1; if(kind == PRED && e1.kind == SUCC )returne1.e1; if(kind == ISZERO && e1.kind == ZERO )returnTrue(); if(kind == ISZERO && e1.kind == SUCC )returnFalse(); if(kind == IF && e1.kind == TRUE )returne2; if(kind == IF && e1.kind == FALSE)returne3; thrownewStuckException(); } // Helper Functions … } Expression root; @DeclarativepublicbooleanwellTyped() {returnroot.wellTyped(); } publicvoidsmallStep()throwsStuckException { root = root.smallStep(); } publicbooleanisFinalState() {returnroot.isValue(); } } Expression smallStep()throwsStuckException { if(isValue())return this; if(!e1.isValue()) { e1 = e1.smallStep();return this; } if(kind == PRED && e1.kind == ZERO )returne1; if(kind == PRED && e1.kind == SUCC )returne1.e1; if(kind == ISZERO && e1.kind == ZERO )returnTrue(); if(kind == ISZERO && e1.kind == SUCC )returnFalse(); if(kind == IF && e1.kind == TRUE )returne2; if(kind == IF && e1.kind == FALSE)returne3; thrownewStuckException(); }

  18. Language Definition classExpressionLanguageimplementsLanguage { … static classExpression { intkind; // TRUE, FALSE, ZERO, SUCC, PRED, ISZERO, IF @TreeExpression e1, e2, e3; @DeclarativebooleanwellTyped() { returnsyntaxOk() && (kind == TRUE ==>true ) && (kind == FALSE ==>true ) && (kind == ZERO ==>true ) && (kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && (kind == PRED ==> e1.wellTyped() && e1.type() == INT) && (kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && (kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type()); } Expression smallStep()throwsStuckException { if(isValue())returnthis; if(!e1.isValue()) { e1 = e1.smallStep();returnthis; } if(kind == PRED && e1.kind == ZERO )returne1; if(kind == PRED && e1.kind == SUCC )returne1.e1; if(kind == ISZERO && e1.kind == ZERO )returnTrue(); if(kind == ISZERO && e1.kind == SUCC )returnFalse(); if(kind == IF && e1.kind == TRUE )returne2; if(kind == IF && e1.kind == FALSE)returne3; thrownewStuckException(); } // Helper Functions … } Expression root; @DeclarativepublicbooleanwellTyped() {returnroot.wellTyped(); } publicvoidsmallStep()throwsStuckException { root = root.smallStep(); } publicbooleanisFinalState() {returnroot.isValue(); } } @DeclarativebooleanwellTyped() { returnsyntaxOk() && (kind == TRUE ==>true ) && (kind == FALSE ==>true ) && (kind == ZERO ==>true ) && (kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && (kind == PRED ==> e1.wellTyped() && e1.type() == INT) && (kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && (kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type()); }

  19. Approach • Defining the language • Searching the state space • Representing the state space • Reducing the state space

  20. Searching • Select an unchecked well typed state if iszero false if 0 false true false

  21. Searching • Check progress and preservation • Progress: Run one small step if iszero false if voidsmallStep()throwsStuckException { … } 0 false true false if true false if false true false

  22. Searching • Check progress and preservation • Preservation: Check if the result is well typed if iszero false if 0 false true false if @DeclarativebooleanwellTyped() { … } true false if false true false

  23. if if if iszero iszero false false iszero succ true if pred 0 0 false true 0 0 0 false if if if true true false false true succ true if pred false true 0 0 false Searching • Identify and prune similar states PRUNED

  24. Need efficient representation and operations for these sets! Search Algorithm Let W be the well typed state space While W is not empty Choose a state s in W Run one step of evaluation on s If Progress or Preservation fail Print out s as a bug trace Let P be the set of states similar to s W = W – P

  25. Approach • Defining the language • Searching the state space • Representing the state space • Reducing the state space

  26. kind = {b0,b1,b2} e1 = {b3} e2 = {b4} e3 = {b5} … kind = {b6,b7,b8} e1 = {} e2 = {} e3 = {} Representing the State Space • Represent a set as a boolean formula • Encode each field as bits (b0, b1, …) • Constrain the bits using boolean operations n1 n1.kind == IF && n1.e1.kind == TRUE (b0 ۸ b1 ۸¬b2) ۸ b3 ۸ (¬b6۸ ¬b7۸¬b8) n2 At AST height 5, a formula representing2,504,790,381well typed states isonly24,117terms long.

  27. Representing the State Space • Initialize to the set of well typed states • Construct a formula describing the type system @DeclarativebooleanwellTyped() { returnsyntaxOk() && ( kind == TRUE ==>true) && ( kind == FALSE ==>true ) && ( kind == ZERO ==>true) && ( kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && ( kind == PRED ==> e1.wellTyped() && e1.type() == INT) && ( kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && ( kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type() ); } boolean formula

  28. Representing the State Space • Initialize to the set of well typed states • Construct a formula describing the type system • Declarative methods • May not use object creations, assignments, or loops • May use ==>, forall, exists operators • Declarative methods translate to small formulas @DeclarativebooleanwellTyped() { returnsyntaxOk() && ( kind == TRUE ==>true) && ( kind == FALSE ==>true ) && ( kind == ZERO ==>true) && ( kind == SUCC ==> e1.wellTyped() && e1.type() == INT) && ( kind == PRED ==> e1.wellTyped() && e1.type() == INT) && ( kind == ISZERO ==> e1.wellTyped() && e1.type() == INT) && ( kind == IF ==> e1.wellTyped() && e1.type() == BOOL && e2.wellTyped() && e3.wellTyped() && e2.type() == e3.type() ); }

  29. Search Algorithm Let W be the well typed state space While W is not empty Choose a state s in W Run one step of evaluation on s If Progress or Preservation fail Print out s as a bug trace Let P be the set of states similar to s W = W – P Use a SAT solver Add ¬P to the SAT solver

  30. Approach • Defining the language • Searching the state space • Representing the state space • Reducing the state space • Dynamic analysis • Static analysis • Other optimizations

  31. if iszero false if 0 false true false if true false if false true false Dynamic Analysis • Discover and prune states that are similar • Touched analysis • Track which fields are accessed • Symbolic execution • Track which fields are accessed and how they are used root.kind == IF && root.e1.kind == ISZERO && root.e1.e1.kind == ZERO (root.kind == IF || root.kind == ISZERO || root.kind == SUCC || root.kind == PRED) && root.e1.kind == ISZERO && root.e1.e1.kind == ZERO

  32. Static Analysis

  33. Static Analysis class WhyStaticAnalysis { privateboolean a, b; publicvoid smallStep() { a = !a; } @Declarative publicboolean wellTyped() { return a || b; } }

  34. a = true b = true Static Analysis class WhyStaticAnalysis { privateboolean a, b; publicvoid smallStep() { a = !a; } @Declarative publicboolean wellTyped() { return a || b; } } Choose a well typed state

  35. a = true a = false b = true b = true Static Analysis class WhyStaticAnalysis { privateboolean a, b; publicvoid smallStep() { a = !a; } @Declarative publicboolean wellTyped() { return a || b; } } Choose a well typed state Check the transition

  36. a = true a = false a = true a = false b = true b = true b = false b = false Static Analysis class WhyStaticAnalysis { privateboolean a, b; publicvoid smallStep() { a = !a; } @Declarative publicboolean wellTyped() { return a || b; } } Choose a well typed state Check the transition Prune similar transitions well typed PRUNED

  37. Static Analysis • Dynamic analysis alone is not always correct! • Need to perform additional checks • Could check each pruned transition separately • Negates the benefits of pruning • We use static analysis to ensure correctness • All pruned transitions checked together • Any error within finite bounds is caught

  38. a = true a = false a = false a = true b b = true b = true b Static Analysis class WhyStaticAnalysis { privateboolean a, b; publicvoid smallStep() { a = !a; } @Declarative publicboolean wellTyped() { return a || b; } } wellTyped = (a || b) Prestate of a pruned transition wellTypedPre = (a || b)a=true = true wellTypedPost= (a || b)a=false= b wellTypedPre wellTypedPost = b Poststate of the pruned transition Not valid when b = false!

  39. Static Analysis • Partially evaluate wellTyped formula • Use SAT solver to check the above implication • If the implication holds then pruning is sound • If not, we have a counterexample • Often, wellTypedPre and wellTypedPost are identical • Checking the implication is trivial then wellTypedPre  wellTypedPost

  40. Other Optimizations • Isomorphism pruning • Prune more when checking heaps • Handling term cloning • Perform symbolic copy • Handling term substitution • Perform incremental substitution

  41. Outline • Motivation • Example • Approach • Experimental Results • Related Work • Conclusions

  42. Experimental Results • We verified type soundness of five languages: • Expression Language • Imperative Language • Featherweight Java • Mini Java • Mini Java with Ownership Types

  43. Experimental Results • Imperative Language • Simple language from [Winskel93, Chapter 2] • Features variables, assignment, conditionals, loops • Features arithmetic, relational, logical operators int a; a := 5; while (a < 7) a := a+1;

  44. Experimental Results • Featherweight Java [Igarashi99] • Subset of Java • Features classes, inheritance, methods, fields class A extends Object { A() { super(); } } class B extends Object { B() { super(); } } class Pair extends Object { Object fst; Object snd; Pair(Object fst, Object snd) { super(); this.fst=fst; this.snd=snd; } Pair setfst(Object newfst) { return new Pair(newfst, this.snd); } }

  45. Experimental Results • Mini Java • Extends Featherweight Java • Allows mutation of objects • Features an explicit heap • Features integers and booleans class Node extends Object { int value; Node(int value) { super(); this.value = value; } Node mutate() { return this.value := this.value + 1; } }

  46. Experimental Results • Mini Java with Ownership Types • [Clarke98;Boyapati03;Aldrich02] • Types are parameterized with owners • Enforces object encapsulation class Node<A,B> extends Object<A> { Object<B> data; Node<A,B> next; Node(Object<B> data, Node<A,B> next) { super(); this.data = data; this.next = next; } } class Stack<A,B> extends Object<A> { Node<this,B> root; Stack(Node<this,B> root) { super(); this.root = root; } Stack<A,B> push(Object<B> data) { return this.root := new Node<this,B>(data, this.root); } }

  47. Experimental Results Checks 2157 well typed IMP programs in about 10 seconds

  48. Experimental Results

  49. Experimental Results We inserted 25 errors into Mini Java with Ownership Types

  50. Experimental Results We inserted 25 errors into Mini Java with Ownership Types

More Related