1 / 43

Bandera: Extracting Finite-state Models from Java Code

Bandera: Extracting Finite-state Models from Java Code. Students and Post-docs. Faculty. James Corbett Matthew Dwyer John Hatcliff. Shawn Laubach Corina Pasareanu Robby Hongjun Zheng. Roby Joehanes Ritesh Desai Venkatesh Ranganath Oksana Tkachuk.

ata
Download Presentation

Bandera: Extracting Finite-state Models from Java Code

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. Bandera: Extracting Finite-state Models from Java Code Students and Post-docs Faculty James Corbett Matthew Dwyer John Hatcliff Shawn Laubach Corina Pasareanu Robby Hongjun Zheng Roby Joehanes Ritesh Desai Venkatesh Ranganath Oksana Tkachuk

  2. Goal: Increase Software Reliability Trends: Size, complexity, concurrency, distributed Cost of software engineer………………………. Cost of CPU cycle……………………………….. Future: Automated Fault Detection

  3. The Dream void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } OK Program or Error trace Checker Property 1: … Property 2: … … Requirement

  4. Model Checking OK Finite-state model or Error trace Model Checker (F W) Line 5: … Line 12: … Line 15:… Line 21:… Line 25:… Line 27:… … Line 41:… Line 47:… Temporal logic formula

  5. ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 L3 Spin Example proctype A(chan in, out) { byte mt; /* message data */ bit vr; L1: mt = (mt+1%MAX); out!mt,1; goto L2; L2: in?vr; if :: (vr == 1) goto L1 :: (vr == 0) goto L3 :: printf(“Error”); goto L5 fi; L3: out!mt,1; goto L2; L4: in?vr; if :: goto L1; :: printf(“Error”); goto L5 fi; L5: out!mt,0; goto L4 } Fragment of Alternating Bit Protocol

  6. Conceptual View Explored State-Space (computation tree) ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 Implementation Pending Seen Before L3 [L1, (mt1, vr1), ….] Fragment of Alternating Bit Protocol Explicit State Model-checking

  7. ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 Pending Seen Before L3 Fragment of Alternating Bit Protocol Explicit State Model-checking Conceptual View Explored State-Space (computation tree) [L1, (mt1, vr1), ….] Implementation [L2, (mt2, vr2), ….] [L1, (mt1, vr1), ….]

  8. ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 Pending Seen Before L3 Fragment of Alternating Bit Protocol Explicit State Model-checking Conceptual View Explored State-Space (computation tree) [L1, (mt1, vr1), ….] [L2, (mt2, vr2), ….] Implementation [L3, (mt3, vr3), ….] [L1, (mt1, vr1), ….] [L5, (mt5, vr5), ….] [L2, (mt2, vr2), ….] [L1, (mt1’, vr1’), ..]

  9. ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 Pending Seen Before L3 Fragment of Alternating Bit Protocol Explicit State Model-checking Conceptual View Explored State-Space (computation tree) [L1, (mt1, vr1), ….] [L2, (mt2, vr2), ….] [L3, (mt3, vr3), ….] Implementation [L5, (mt5, vr5), ….] [L1, (mt1, vr1), ….] [L1, (mt1’, vr1’), ..] [L2, (mt2, vr2), ….] [L3, (mt3, vr3), ….]

  10. ?b1 L1 L4 ?b0 ?b1 !a1 ?err !a0 L2 L5 ?err ?b0 ?a1 Pending Seen Before L3 Fragment of Alternating Bit Protocol Explicit State Model-checking Conceptual View Explored State-Space (computation tree) [L1, (mt1, vr1), ….] [L2, (mt2, vr2), ….] [L3, (mt3, vr3), ….] [L5, (mt5, vr5), ….] Implementation [L1, (mt1’, vr1’), ..] [L1, (mt1, vr1), ….] [L2, (mt2, vr2), ….] [L3, (mt3, vr3), ….] [L5, (mt5, vr5), ….]

  11. Why Try to Use Model Checking for Software? • Automatically check, e.g., • invariants, simple safety & liveness properties • absence of dead-lock and live-lock, • complex event sequencing properties, • In contrast to testing, gives complete coverage by exhaustively exploring all paths in system, • It’s been used for years with good success in hardware and protocol design “Between the window open and the window close, button X can be pushed at most twice.” This suggests that model-checking can complement existing software quality assurance techniques.

  12. OK Finite-state model or Line 5: … Line 12: … Line 15:… Line 21:… Error trace Model Checker (F W) Temporal logic formula What makes model-checking software difficult? • Model construction Problems using existing checkers: • State explosion • Property specification • Output interpretation

  13. Gap Model Construction Problem void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } • Semantic gap: Model Checker Program Model Description Programming Languages methods, inheritance, dynamic creation, exceptions, etc. Model Description Languages automata

  14. OK Finite-state model or Line 5: … Line 12: … Line 15:… Line 21:… Error trace Model Checker (F W) Temporal logic formula What makes model-checking software difficult? • Model construction Problems using existing checkers: • State explosion • Property specification • Output interpretation

  15. Property Specification Problem • Difficult to formalize a requirement in temporal logic “Between the window open and the window close, button X can be pushed at most twice.” …is rendered in LTL as... []((open /\ <>close) -> ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ (!pushX U close))))))))))

  16. Property Specification Problem Forced to state property in terms of model rather than source: • We want to write source level specifications... Heap.b.head == Heap.b.tail • We are forced to write modellevel specifications... (((_collect(heap_b) == 1)\ && (BoundedBuffer_col.instance[_index(heap _b)].head == BoundedBuffer_col.instance[_index(heap _b)].tail) )\ || ((_collect(heap _b) == 3)\ && (BoundedBuffer_col_0.instance[_index(heap _b)].head == BoundedBuffer_col_0.instance[_index(heap _b)].tail) )\ || ((_collect(heap _b) == 0) && TRAP))

  17. OK Finite-state model or Line 5: … Line 12: … Line 15:… Line 21:… Error trace Model Checker (F W) Temporal logic formula What makes model-checking software difficult? • Model construction Problems using existing checkers: • State explosion • Property specification • Output interpretation

  18. Bit x1,…,xN 2^N states State Explosion Problem • Moore’s law and algorithm advances can help • Holzmann: 7 days (1980) ==> 7 seconds (2000) • Explosive state growth in software limits scalability • Cost is exponential in the number of components

  19. OK Finite-state model or Line 5: … Line 12: … Line 15:… Line 21:… Error trace Model Checker (F W) Temporal logic formula What makes model-checking software difficult? • Model construction Problems using existing checkers: • State explosion • Property specification • Output interpretation

  20. Line 5: … Line 12: … Line 15:… Line 21:… Line 25:… Line 27:… … Line 41:… Line 47:… Gap Error trace Output Interpretation Problem void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } • Raw error trace may be 1000’s of steps long Model Description Program • Must map line listing onto model description • Mapping to source is made difficult by • Semantic gap & clever encodings of complex features • multiple optimizations and transformations

  21. Graphical User Interface Optimization Control Checker Inputs Bandera Temporal Specification void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } Model Checkers Transformation & Abstraction Tools Checker Outputs Java Source Error Trace Mapping Bandera Bandera:An open tool set for model-checking Java source code

  22. Static Analyses Abstract Interpretation Optimizations void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } Slicing Java Source Model Compiler Model Description Model extraction: compiling to model checker inputs: Addressing theModel Construction Problem • Numerous analyses, optimizations,two intermediate languages, multiple back-ends • Slicing, abstract interpretation, specialization • Variety of usage modes: simple...highly tuned

  23. Using the pattern system: 2-bounded existence Between {open} and {close} {pushX} exists atMost {2}times; Addressing theProperty Specification Problem An extensible language based on field-tested temporal property specification patterns []((open /\ <>close) -> ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ ((!pushX /\ !close) U (close \/ ((pushX /\ !close) U (close \/ (!pushX U close))))))))))

  24. Property Generate models customized wrt property! • Result: multiple models --- even as many as one per property Addressing theState Explosion Problem void add(Object o) { buffer[head] = o; head = (head+1)%size; } … Java Source Model Compiler Model Descriptions • Aggressive customization via slicing, abstract interpretation, program specialization

  25. void add(Object o) { buffer[head] = o; head = (head+1)%size; } Object take() { … tail=(tail+1)%size; return buffer[tail]; } Java Source Line 5: … Line 12: … Line 15:… Line 21:… + simulator Like a debugger: error traces mapped back to source Addressing theOutput Interpretation Problem Model Description Intermediate Representations Model Checker Model Compiler Error trace • Run error traces forwards and backwards • Program state queried • Heap structures navigated • Locks, wait sets, blocked sets displayed

  26. Translators Property Tool Abstraction Engine BIR Analyses BIRC SPIN dSPIN Java Jimple Parser SMV Slicer Simulator JPF Error Trace Display Bandera Architecture

  27. Front End • Translates Java source to Jimple IR • Supports specification of property • Provides debugger-like step facilities for error traces Label1: if (x <= 0) goto Label2; t0 = y * 2; x = t0; Label2: … if (x > 0) x = y * 2; Java Jimple

  28. Requirement: If a buffer becomes full, it will eventually become non-full. Bandera Specification: FullToNonFull: forall[b:BoundedBuffer]. {Full(b)} leads to {!Full(b)} globally; Property Specification /** * observable * EXP Full: (head == tail); */ class BoundedBuffer { Object [] buffer; int head, tail, bound; public synchronized void add(Object o) {…} public synchronized Object take () {…} }

  29. indirectly relevant Slice mentioned in property Resulting slice Property-directed Slicing • slicing criterion generated automatically from observables mentioned in the property Source program • backwards slicing automatically finds all components that might influence the observables.

  30. Slicing Criterion All statements that assign to head, tail. removed by slicing Included in slicing critirion indirectly relevant Property-directed Slicing /** * @observable EXP Full: (head == tail) */ class BoundedBuffer { Object [] buffer_; int bound; int head, tail; public synchronized void add(Object o) { while ( tail == head ) try { wait(); } catch ( InterruptedException ex) {} buffer_[head] = o; head = (head+1) % bound; notifyAll(); } ... }

  31. int (n<0) : neg (n==0): zero (n>0) : pos Signs Signs x = zero; if (x == zero) x = pos; neg zero pos AbstractionSpecializer Collapses data domains via abstract interpretation: Code Data domains int x = 0; if (x == 0) x = x + 1;

  32. PVS BASL Compiler Concrete Type Abstract Type Inferred Type Variable Bandera Abstraction Specification Language Jimple Abstracted Jimple Abstraction Engine Jimple Abstraction Component Functionality x int Signs y int Signs Signs done bool Bool Abstraction Library count int intAbs …. …. o Object Point b Buffer Buffer

  33. Compiled Abstraction Specification abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n < 0 -> {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end operator + add begin (NEG , NEG) -> {NEG} ; (NEG , ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS , ZERO) -> {POS} ; (POS , POS) -> {POS} ; (_,_)-> {NEG, ZERO, POS}; /* case (POS,NEG), (NEG,POS) */ end public class Signs { public static final int NEG = 0; // mask 1 public static final int ZERO = 1; // mask 2 public static final int POS = 2; // mask 4 public static int abstract(int n) { if (n < 0) return NEG; if (n == 0) return ZERO; if (n > 0) return POS; } public static int add(int arg1, int arg2) { if (arg1==NEG && arg2==NEG) return NEG; if (arg1==NEG && arg2==ZERO) return NEG; if (arg1==ZERO && arg2==NEG) return NEG; if (arg1==ZERO && arg2==ZERO) return ZERO; if (arg1==ZERO && arg2==POS) return POS; if (arg1==POS && arg2==ZERO) return POS; if (arg1==POS && arg2==POS) return POS; return Bandera.choose(7); /* case (POS,NEG), (NEG,POS) */ }

  34. Automatic Generation Example: Start safe, then refine:+(NEG,NEG)={NEG,ZERO,POS} Forall n1,n2: neg?(n1) and neg?(n2) implies not pos?(n1+n2) Proof obligations submitted to PVS... Forall n1,n2: neg?(n1) and neg?(n2) implies not zero?(n1+n2) Forall n1,n2: neg?(n1) and neg?(n2) implies not neg?(n1+n2) Specification Creation Tools abstraction Signs abstracts int begin TOKENS = { NEG, ZERO, POS }; abstract(n) begin n < 0 -> {NEG}; n == 0 -> {ZERO}; n > 0 -> {POS}; end operator + add begin (NEG , NEG) -> {NEG} ; (NEG , ZERO) -> {NEG} ; (ZERO, NEG) -> {NEG} ; (ZERO, ZERO) -> {ZERO} ; (ZERO, POS) -> {POS} ; (POS , ZERO) -> {POS} ; (POS , POS) -> {POS} ; (_,_)-> {NEG, ZERO, POS}; end

  35. Back End • Bandera Intermediate Representation (BIR) • guarded command language • includes: locks, threads, references, heap • info to help translators (live vars, invisible) loc s5: live { r0, r1 } when lockAvail(r0.lock) do { lock(r0.lock); } goto s6; loc s6: live { r1 } when true do invisible { r1.count = 0;} goto s7; entermonitor r0 r1.count = 0; … Jimple BIR

  36. Bounded Buffer BIR process BoundedB() BoundedBuffer_ref = ref { BoundedBuffer_col, BoundedBuffer_col_0 }; BoundedBuffer_rec = record { bound_ : range -1..4; head_ : range -1..4; tail_ : range -1..4; BIRLock : lock wait reentrant; }; BoundedBuffer_col : collection [3] of BoundedBuffer_rec; BoundedBuffer_col_0 : collection [3] of BoundedBuffer_rec; ……. ………. loc s34: live { b2, b1, add_JJJCTEMP_0, add_JJJCTEMP_6, add_JJJCTEMP_8 } when true do invisible { add_JJJCTEMP_8 := (add_JJJCTEMP_6 % add_JJJCTEMP_8); } goto s35; loc s35: live { b2, b1, add_JJJCTEMP_0, add_JJJCTEMP_8 } when true do { add_JJJCTEMP_0.head_ := add_JJJCTEMP_8; } goto s36; loc s36: live { b2, b1, add_JJJCTEMP_0 } when true do { notifyAll(add_JJJCTEMP_0.BIRLock); } goto s37; loc s37: live { b2, b1, add_JJJCTEMP_0 } when true do { unlock(add_JJJCTEMP_0.BIRLock); } goto s38;

  37. Bounded Buffer Promela typedef BoundedBuffer_rec { type_8 bound_; type_8 head_; type_8 tail_; type_18 BIRLock; } … … loc_25: atomic { printf("BIR: 25 0 1 OK\n"); if :: (_collect(add_JJJCTEMP_0) == 1) -> add_JJJCTEMP_8 = BoundedBuffer_col. instance[_index(add_JJJCTEMP_0)].tail_; :: (_collect(add_JJJCTEMP_0) == 2) -> add_JJJCTEMP_8 = BoundedBuffer_col_0. instance[_index(add_JJJCTEMP_0)].tail_; :: else -> printf("BIR: 25 0 1 NullPointerException\n"); assert(0); fi; goto loc_26; }

  38. Translators • Plug-in component that interfaces to specific model checker • Translates BIR to checker input language • Parses output of checker for error trace • Currently • SPIN, dSPIN, SMV translators complete • JPF (from NASA Ames) integrated • XMC, FDR translators in progress

  39. Case Studies • Small examples thus far (< 2000 loc) • illustrating use of property-pattern system and other components • Scheduler from DEOS real-time OS kernel • (1600, 22 classes, seven tasks) • Now trying systems up to 20,000 loc • collection of 15 open-source 100% pure Java • Jigsaw web-server from W3C • Tomcat, James(from Apache/Jakarta) • In general, 1-2 minutes for model extraction on (~2000k systems) • State space reductions can dramatically reduce cost

  40. Summary • Bandera provides an open platform for experimentation • Separates model checking from extraction • uses existing model checkers • supports multiple model checkers • Specialize models for specific properties using automated support for slicing, abstraction, etc. • Designed for extensibility • well-defined internal representations and interfaces • We hope this will contribute to the definition of APIs for software model-checkers

  41. Context of Project • Researchers with different backgrounds (programming languages, static analysis, verification of concurrent systems, software engineering) • Started on Bandera in November 1998 (previously built verification tools for Ada) • Funding from NASA, National Science Foundation, Honeywell, US Air Force

  42. Current Status • A reasonable subset of concurrent Java • not handled: recursive methods, exceptions, inner classes, native methods, libraries(*) • You can play around with a “pre-alpha” version of the tools accompanied by a draft tutorial • Public release: October 2000 http://www.cis.ksu.edu/santos/bandera

  43. Schedule of BRICS Mini-Course • Monday -- Overview • overview talk • basic demo • Tuesday -- Specifying Temporal Properties of Software • overview of temporal specification • review of CTL, LTL • temporal specification design patterns • example driven presentation of Bandera’s specification tools • Wednesday -- Details of Bandera Components • slicing concurrent Java programs • Bandera abstraction tools • model generation via Bandera’s back-end • summary of case studies (e.g., space-craft controller examples)

More Related