520 likes | 619 Views
Typestate Verification: Abstraction Techniques and Complexity Results. J. Field, D. Goyal, G. Ramalingam IBM T.J. Watson Research Center. E. Yahav School of Computer Science Tel-Aviv University. Motivation. Component a library with cleanly encapsulated state. Client
E N D
Typestate Verification: Abstraction Techniques and Complexity Results J. Field, D. Goyal, G. Ramalingam IBM T.J. Watson Research Center E. Yahav School of Computer Science Tel-Aviv University
Motivation Component a library with cleanly encapsulated state Client a program that uses the library
Approach Component a library with cleanly encapsulated state Client a program that uses the library • Tailor certification procedure to the specification being verified • CanvasProject (Component Annotation, Verification and Stuff) • Lightweight Specification • "correct usage" rules a client must follow • "call open() before read()" Certification does the client program satisfy the lightweight specification?
Typestate Checking[Strom and Yemini 1986] • Statically verify that programs satisfy certain kinds of temporal safety properties • A file should be opened before it can be read • A file should not be read after it is closed • … • Many recent approaches to verification based on typestate checking • Interaction of aliasing and typestate checking not well understood
Goals • How to increase precision oftypestate checking for programs with aliasing • Specialized abstractions • Exploit nature of property being verified • Exploit nature of programs being verified • Complexity bounds • Relate difficulty of verification to the nature of the property/programs being verified
read read close close read closed error not-closed close Specifications as Finite Automata • Automaton defines set of valid operation sequences that can be performed on an object • The set of valid sequences is prefix-closed • all transitions from error state are to itself • Can also use regular expressions • implicit prefix-closure (in this talk) • read*;close
? PSPACE-hard Undecidable No aliasing Shallow aliasing (1-level pointers) Two or morelevels of pointers w/o recursive data structures Recursive data structures Precise Typestate Checking and Aliasing • Precise modulo common assumption that all paths in the program are executable O(|S||V||P|)
Typestate Checking + Shallow Aliasing x := new File(); y := new File(); z := y; if (?) { y.close(); z := x; } z.read();
Lightweight Specification read read close close read closed error not-closed close Common Approach: Two-Phase Analysis Client Program • Break certification into two phases • separate points-to analysis • apply typestate checking • Separation of analyses can lead to imprecision Points-to analysis Typestate checking
Loss of Precision in Two-phased Approach file 1 created x := new File(); y := new File(); z := y; if (?) { y.close(); z := x; } z.read(); file 2 created file 2 closed z may point to file 1 or file 2 file 2 may be closed read may be erroneous (independent attributes analysis)
Is Precise but Efficient Typestate Checking Possible? Not all finite state properties are equally hard to verify!
Plan • Property Classes • Omission-Closed Properties • Repeatable-Enabling Sequence Properties • Program Classes • In-degree Bounded Aliasing • Summary
Omission-closed Properties • Every subsequence of a valid sequence is also valid • read*;close • read;read;read;read;close • There exists a finite set of forbidden subsequencess.t. a sequence is invalid iff it contains some forbidden subsequence as a subsequence • close;read • close;close • Verifiable in polynomial time!
Example Selected false predicates <{x,y},*>, <{x},{closed,error}>, <{y},{closed,error}>… x := new File(); y := new File(); z := y; if (?) { y.close(); z := x; } z.read(); <{x,y},*>, <{x},{closed,error}>, <{z},{closed,error}>… <{x},{closed,error}>,… <{z},{closed,error}>,…
Ensuring Precise Polynomial Analysis • How do we perform verification in polynomial time without losing precision? • Ensuring polynomial time • Independent attribute analysis • Polynomial number of predicates • Ensuring no loss of precision • Require set of predicates to be disjunctively WP-closed
Selecting Predicates using Iterated Weakest Precondition • Process applied to a specific property and not to a specific client program • Start with a set of predicates of interest W = {<Error>} • Repeat • for every predicate p in W and every statement form st, • compute WP(st,p) • simplify WP(st,p) • add the disjuncts of simplified formula to W • Resulting set W is disjunctively WP-closed
read read close close read closed error not-closed close Applying IWP To read*close <{x,y}, {not-closed,closed,error}> <{x}, {closed,error}><{x,y}, {not-closed,closed,error}> <{x}, {closed,error}> y.read() y.close() <{x}, {closed,error}> <Error><{x}, {closed,error}> <Error><{x}, {closed,error}> x.read() x.close() <Error>
Example Revisited Selected false predicates <{x,y},*>, <{x},{closed,error}>, <{y},{closed,error}>… x := new File(); y := new File(); z := y; if (?) { y.close(); z := x; } z.read(); <{x,y},*>, <{x},{closed,error}>, <{z},{closed,error}>… <{x},{closed,error}>,… <{z},{closed,error}>,…
read not-closed closed, error closed, error read close error close Relevant predicate families Selecting Predicates for Omission-Closed Properties • Construct the (part of) predecessor graph on sets of states, reachable from {error} read <Error> <{x}, { closed, error}> <{x,y}, {not-closed, closed, error}>
Eureka Steps in Simplifying Weakest-Preconditions • WP (x.read(), <Error>) could be simplified to <Error> <{x}, {closed,error}> or <Error> <{x}, {closed}> • Choosing the first form is critical … the second form will not lead to a polynomial time solution!
What about properties that are not omission-closed? • Can we always find similar polynomial-time “precise” verification algorithms? • Unfortunately, that is unlikely …
Repeatable Enabling Sequence Properties • RES properties • a sequence c is invalid, but b+c is valid • open+;read • read • open;open;read • Verification of RES properties • NP-complete for acyclic programs • PSPACE-complete for general programs • no polynomial bound exists for the length of the shortest error path (unless PSPACE = NP)
open+;readexample read*;closeexample … p1.open(); … p2.open(); … … pk.open(); … q.read(); … p1.close(); … p2.close(); … … pk.close(); … q.read(); The Intuition Can q = p1? … Can q = pk? Is there a path along which q p1 & … & q pk ? k easy questions a hard question
Is that all? • No… • some properties are neither omission-closed nor repeatable-enabling-sequence properties • For example • open;read • not omission-closed - open;read valid but subsequence readnot valid • open is an enabling sequence (enables read), but not repeatable - open;open;readis not valid • more results in the paper… • (lock;unlock)*
Taking A Different Angle • Recap: some property classes are hard to verify • e.g., open+;read • What to do? • Exploit properties that programs usually have • A single object usually not simultaneously pointed by a large number of program variables • Is it possible to do finite-state verification efficiently at least for such programs?
Limited Aliasing • Arbitrary finite state properties can be verified in time O(nk+1) • programs of size n, maximum aliasing factor k • Naive approaches take exponential time
Limited Aliasing – Key Ideas • Use a new predicate vocabulary • [A, s] denotes • all variables in A point to the same object O • O is in state s • no variable not in A points to object O • Use a forward propagation analysis • Lazily introduce predicates • Complexity proportional to number of predicate instances that take non-false value
Beyond Shallow Programs:Heap Analysis • Use instrumented heap analysis - heap analysis guided by properties of heap objects of interest • Parametric shape analysis via 3-valued logic (Sagiv, Reps, Wilhelm, TOPLAS 02) • Establishing Local Heap Safety Properties with Applications to memory-management (Shaham, Yahav, Kolodner, Sagiv, SAS 03) • Our abstractions can be used to define heap object properties of interest • Improve precision of the analysis
Related Work • Type-based • Deline and Fahndrich, PLDI 2001 (Vault) • Foster, Terauchi, and Aiken, PLDI 2002 • Selective path-sensitivity • Das, Lerner, and Seigle, PLDI 2002 (ESP) • Engler, Chelf, Chou and Hallem, OSDI 2000 • Complete abstract interpretations • Giacobazzi, Ranzato, and Scozzari JACM 2000 • Other • Corbett et.al., ICSE 2000 (Bandera) • Ball and Rajamani, SPIN 2001 (SLAM) • Henzinger et al., POPL 2002 (BLAST) • Naumovich, Clarke, Osterwell, and Dwyer, FLAVERS (1997) • …
The End http://www.cs.tau.ac.il/~yahave
DISCARDED SLIDES • Slides beyond this point are discarded slides
Verification by counting • Counting “how often” a predicate holds true can be done efficiently for acyclic programs and certain kinds of predicates • Certain finite state properties can be verified efficiently using such a counting approach in the case of acyclic graphs • Can be applied to programs with loops by “unrolling loops” … • effective technique for properties where bounds can be established on the length of shortest error paths
Example x := new File(); y := new File(); z := y; if (?) { y.close(); z := x; } z.read(); z points to unclosed file z points to closed file z points to unclosed file z points to unclosed file read is safe
Example f := new File(); While (?) { f.read(); … if (?) { f.close(); f := new File(); } } read is safe
IWP: Omission-Closed Properties • WP (x.op(), <A,S>) = ? • pred(S,op) = set of states whose successor on operation op is in S • case 1: if pred(S,op) = S, then WP (x.op(), <A,S>) = <A,S> • case 2: if pred(S,op) S, then WP (x.op(), <A,S>) = <A {x}, pred(S,op)> <A,S>
IWP: Omission-Closed Properties • case 3: if NOT (pred(S,op) Ê S) ? • then WP (x.op(), <A,S>) is more complicated … it cannot be expressed as a predicate of the form <A,S>. • However, any predicate <A,S> that is relevant for verification of an omission-closed property satisfies pred(S,op) Ê S for every op …
Relevant Predicates forOmission-closed Properties • Which predicates are relevant? Base < { }, {error} > is relevant Induction if <A,S> is relevant after x.op() and if pred(S,op) S, then <A {x}, pred(S,op)> is relevant
read read close close read closed error not-closed close Applying IWP To read*close WP (x.read(), <{ }, {error}>) = <{ }, {error}> <{x}, {closed,error}> WP (x.close(), <{ }, {error}>) = <{ }, {error}> <{x}, {closed,error}> WP (y.read(), <{x}, {closed,error}>) = <{x}, {closed,error}> WP (y.close(), <{x}, {closed,error}>) = <{x}, {closed,error}> <{x,y}, {not-closed,closed,error}>
Abstract Transformers • Computed using weakest precondition • WP(x.read(),<Error>) <Error><{x}, {closed,error}> x.read() <Error>
Iterated Weakest Precondition: A Methodology For Designing Analyses • Start with a set B of predicates of interest • Iteratively compute a superset T of B such that • for every predicate p of interest and every possible statement st, compute WP(st,p) • simplify WP(st,p) and identify the disjuncts of simplified formula as predicates of interest • Resulting set is disjunctively WP-closed
Independent Attribute Predicate Abstraction • A special class of abstract interpretations • Defined by a set of predicates W • Predicate = Boolean function of the concrete state • “there exists an object in the error state” • “variables x and y point to the same object” • Concrete state abstracted by value of the set of predicates • A function from W to {true, false} • Independent attribute analysis • A set of concrete states abstracted by a function from W to {true, false, maybe}
Precise Predicate Abstraction Using Independent Attributes • W = set of predicates for a program P • For every predicate pi in W, and every statement St in P, there exist predicates pj1, pj2,…,pjm in W WP (St, pi) = pj1-pj2-…-pjm • Answering “exists a path making predicate w true at program point q” can be done in O(|W||P|) time
Predicates For read*close • For a program P with a set of variables V • The set of predicates W • < Error > • < {x}, {closed,error}> for every variable x • <{x,y}, {...}> for every pair of variables x and y • O(|V|2) predicates • Precise verification can be done in time O(|V|2|P|)
open;read • open;readcan be expressed as two constraints • open;open, read;open, and read;read are forbidden subsequences • an omission-closed property that can be efficiently verified • read should be preceded by open • the repeatable-enabling-sequence open+;read • Is open+;read easy to verify for programs guaranteed not to contain the forbidden subsequences open;open,read;open, and read;read ?
The Intuition open;readexample • Can pi = pj, for some i <> j? • then, stop; Error! … p1.open(); … p2.open(); … … pk.open(); … q.read(); Is there a path along which q <> p1 & q <> p2 & … & q <> pk ? • How often is q = p1? • … • How often is q = pk? How often is q = pi for some i? not the same Error! How often is q.read() executed?