SlideShare uma empresa Scribd logo
1 de 30
Baixar para ler offline
Finding Bugs Efficiently with a SAT Solver




      Julian Dolby, Mandana Vaziri, Frank Tip
      IBM Thomas J. Watson Research Center



  FSE 2007—Dubrovnik, Croatia—September 6, 2007
Outline




• Background
• Miniatur Contributions
• Example
• Miniatur Evaluation
• Related Work
• Conclusions and Future Work
Background—Finding Bugs
• Finding bugs must balance coverage and precision
  – Tools must find bugs to be useful
  – Tools must minimize false positives to be useful
Background—Finding Bugs
• Testing approaches find real bugs
  – Each test is an actual execution, so all bugs real
  – Coverage depends upon test suite, so often spotty
Background—Finding Bugs
• Conservative static analysis approaches find all bugs
  – Conservative approximation of all executions
  – Can find false positives due to approximation
Background—Systematic Underapproximation
• Systematic underapproximation blends testing and analysis
  – Explores all possible concrete execution within a finite set
  – Real bugs and total coverage within for set of executions
Background—Systematic Underapproximation
• Key issue is choosing a “good” set of execution
  – Set must be tractable
  – Set must cover interesting range of all executions
• Use “small scope hypothesis” to bound set of executions
  – Hypothesis: most data structure bugs need only few objects
  – E.g. Collection bugs can be seen by inserting few elements
  – Explore executions with small heaps (also bound loops)




            (small scope)     (other approximation)
Background—Finding Bugs with SAT

• Given program, specification, find concrete counter example
• Use relational first-order logic (FOL) (Alloy [Jackson et al])
   – Universe of atoms, and bounded relations over atoms
   – Relational operators, first-order formulae over relations
   – Tool (Kodkod[Torlak et al]) translates to CNF for SAT solver
• Java in Relational FOL [Vaziri et al] [Taghdiri et al] [Dennis et al]
   – Heap objects as atoms, types as unary relations
   – Fields as binary relations, code as formulae
   – Encode integer operations using bit sets
   – Solve FOL formula program ∧ ¬(spec)
Miniatur Contributions

• Supports much larger range of integers than previous work
   – Integers represented by one atom per power of 2
   – Enables e.g. use of hashCode in updating a collection
• Novel sparse representation of array objects
   – Allows subset of array indices to have values
   – Enables Miniatur to handle array-based collections
• Novel sliced translation based on control dependence
• General theoretical condition for slicing relational formulae
• Demonstration on real collections and a few real programs
   – Arrays, integers enable analyzing all Java collections
   – Integers allow checking Java equality contracts
Example—HashMap Data

class HashMap ... {
  Entry[] table; ...         HashM ap ← {H1}
  class Entry {              Array ← {A1}
    Object key;
                             Entry ← {E1}
    Object value;
                             Object ← {A1, E1, H1, K1, V 1}
    int hash;
                             table ← { H1, A1 }
    Entry next;
...}}                        key ← { E1, K1 }
                             value ← { E1, V 1 }
                             hash ← { E1, #65 }
                             I ← { A1, N 1, #5 }
                             V ← { A1, N 1, E1 }
Example—HashMap Data

class HashMap ... {
  Entry[] table; ...         HashM ap ← {H1}
  class Entry {              Array ← {A1}
    Object key;
                             Entry ← {E1}
    Object value;
                             Object ← {A1, E1, H1, K1, V 1}
    int hash;
                             table ← { H1, A1 }
    Entry next;
...}}                        key ← { E1, K1 }
                             value ← { E1, V 1 }
                             hash ← { E1, #1 , E1, #64 }
                             I ← { A1, N 1, #1 , A1, N 1, #4 }
                             V ← { A1, N 1, E1 }
Example—HashMap.put



public Object put(Object k, Object v) {
  int h = k.hashCode();
  int i = h % table.length;
  for (Entry e = table[i]; e != null; e = e.next) {
    ...
  }
  modCount++;
  table[i] = new Entry(h, k, v, table[i]);
  return null;
Example—HashMap.put



public Object put(Object k, Object v) {
  int h = k.hashCode();
  int i = h % table.length;
  for (Entry e = table[i]; e != null; e = e.next) {
    ...
  }
  modCount++;
  table[i] = new Entry(h, k, v, table[i]);
  return null;
Example—HashMap.put

public Object put(Object k, Object v) {
  int h = k.hashCode();
  int i = h % table.length;
  Entry e = table[i];
  if (e != null) { ...
    e = e.next
    if (e != null) { ...
      e = e.next
      if (e != null) goto end;
  } }
  modCount++;
  table[i] = new Entry(h, k, v, table[i]);
  return null;
Example—HashMap.put

public Object put(Object k, Object v) {
  int h = k.hashCode();
  int i = h % table.length;
  Entry e = table[i]0;
  if (e != null) { ...
    e1 = e.next;
    if (e1 != null) { ...
      e2 = e1.next;
      if (e2 != null) goto end;
  } }
  modCount1 = modCount0 + 1;
  table[i]1 = new Entry(h, k, v, table[i]0);
  return null;
Example—HashMap.put
public Object put(Object k, Object v) {
  int h = k.hashCode();
  int i = h % table.length;
  Entry e = table[i]0;
  if (e != null) { ...
    e1 = e.next;
    if (e1 != null) { ...
      e2 = e1.next;
      if (e2 != null) goto end;
  } }
  modCount1 = modCount0 + 1;
  table[i]1 = new Entry(h, k, v, table[i]0);
  A: assert table[i]1.next == null; // perfect hashing
  return null;
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {E[table].x.E[V 1] |sum(E[table].x.E[I1]) = E[i] }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {E[table].x.E[V 1] |sum(E[table].x.E[I1]) = E[i] }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1}, next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {{A1} .x.E[V 1] |sum({A1} .x.E[I1]) = 5 }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {{A1} . {N 1} .E[V 1] |sum({A1} . {N 1} .E[I1]) = 5 }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {{A1} . {N 1} .E[V 1] |sum({#1, #4}) = 5 }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {{A1} . {N 1} .E[V 1] |5 = 5 }
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     E[table[i]].E[next]
     E[table[i]]   ←     {E1}
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Expression for assert table[i]1.next == null
             ¬ (Guard(A) → E[table[i].next == null])

E[table[i].next == null]     ←      E[table[i].next] = {N ull}
E[table[i].next]   ←     {N ull}
     E[table[i]]   ←     {E1}
                   ...
       sum(x)      ←       xi ∈x   int(xi )
         int(j)    ←     int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . .

                                        table ← {A1} , next ← { E1, N ull }
                                        T 1 ← { A1, N 1 } , i ← 5
                                        I1 ← { A1, N 1, #1 , A1, N 1, #4 }
                                        V 1 ← { A1, N 1, E1 }
Guard for assert table[i]1.next == null

E[e2! = null] = F alse ∨ E[e1! = null] = F alse ∨ E[e! = null] = F alse
Evaluation

• Miniatur tool embodies our techniques
  – Uses WALA for control dependence and other analyses
  – Uses Kodkod to generate CNF
  – Uses Minisat as backend SAT solver
• Evaluated structural assertions in java.util collections
  – Check that size fields accurately reflect data structure
  – Use driver that inserts arbitrary objects into collection
• Evaluated java equality contracts on open-source codes
  – (1) reflexive, (2) symmetric, (3) transitive, (4) non-null,
  – (5) hashCode, (6-9) compareTo properies
Evaluation Results: Testing java.util
class        formula                                     Time (s)   Lines
LinkedList   this.size = |this.header.next∗ − null|           8.2    111
TreeMap      this.size =                                     67.4   12592
             |count(this.root.(lef t + right)∗ − null|
TreeSet      this.m.size =                                   80.0   12667
             |this.m.root.(lef t + right)∗ − null|
HashMap      this.size = |this.table[].next∗ − null|         30.0    1107
HashSet      this.map.size =                                 34.8    1129
             |(this.map.table[].next∗ − null|

• Encode correctness of size fields
• Check expressive properties against complex collections
• Heap size per type, Loop unrolling
Evaluation Results: Testing Equals Contracts
• Test each property of each equals method using harness
  public static void equalsTester(Object a, Object b) {
    if (a.equals(b)) assert b.equals(a); }

• Evaluated several common, open-source benchmarks
  – Antlr, BCEL, Hsqldb, java cup
  – Found 20 concrete violations (of 2, 3, 5, 6, 7)
  – Most tests ran within 2 minutes
• Bugs illustrated by concrete counter-examples
   argument a                               argument b
   ArrayType3                               ArrayType2
   type=54304                               type=9181
   basic type=UninitializedObjectType3      basic type=anonType3
   ...                                      ...
Related Work

• Most-closely related work is checking Java with Alloy
  – Vaziri et al, Taghdiri et al, Dennis et al
  – Miniatur handles more of Java, scales better
• SATURN checks C using SAT
  – Uses manually-tailored summaries
  – Checks less-rich properties
  – Better scaling than Miniatur
• SMT solvers
  – Mix SAT with theories for arithmetic, arrays, etc
  – Can prove properties within particular theories
  – Current SMT solvers less expressive
Conclusions and Future Work
• Miniatur makes SAT-based checking for Java practical
  – Extends prior work to better handle integers, arrays
  – New, sound slicing mechanism for scalability
 → Handles real properties on real programs
 → Deep structural properties on real data structures
• Future work
  – Refinement-based approach to unrolling loops
  – Model concurrency

Mais conteúdo relacionado

Mais procurados

Interpolation of Cubic Splines
Interpolation of Cubic SplinesInterpolation of Cubic Splines
Interpolation of Cubic SplinesSohaib H. Khan
 
Les nouveautés de C# 6
Les nouveautés de C# 6Les nouveautés de C# 6
Les nouveautés de C# 6Microsoft
 
Defining Functions on Equivalence Classes
Defining Functions on Equivalence ClassesDefining Functions on Equivalence Classes
Defining Functions on Equivalence ClassesLawrence Paulson
 
Pre-Cal 40S Slides February 29, 2008
Pre-Cal 40S Slides February 29, 2008Pre-Cal 40S Slides February 29, 2008
Pre-Cal 40S Slides February 29, 2008Darren Kuropatwa
 
Functions and graphs
Functions and graphsFunctions and graphs
Functions and graphsSujata Tapare
 
Lecture 7 data structures and algorithms
Lecture 7 data structures and algorithmsLecture 7 data structures and algorithms
Lecture 7 data structures and algorithmsAakash deep Singhal
 
The Ring programming language version 1.5.3 book - Part 24 of 184
The Ring programming language version 1.5.3 book - Part 24 of 184The Ring programming language version 1.5.3 book - Part 24 of 184
The Ring programming language version 1.5.3 book - Part 24 of 184Mahmoud Samir Fayed
 
Math 4 graphing rational functions
Math 4 graphing rational functionsMath 4 graphing rational functions
Math 4 graphing rational functionsLeo Crisologo
 
On the Design of a Galculator
On the Design of a GalculatorOn the Design of a Galculator
On the Design of a GalculatorPaulo Silva
 
Kotlin for Android Developers - 2
Kotlin for Android Developers - 2Kotlin for Android Developers - 2
Kotlin for Android Developers - 2Mohamed Nabil, MSc.
 
6 slopes and difference quotient x
6 slopes and difference quotient x6 slopes and difference quotient x
6 slopes and difference quotient xTzenma
 
List and Dictionary in python
List and Dictionary in pythonList and Dictionary in python
List and Dictionary in pythonSangita Panchal
 
Data Visualization 2020_21
Data Visualization 2020_21Data Visualization 2020_21
Data Visualization 2020_21Sangita Panchal
 

Mais procurados (20)

Interpolation of Cubic Splines
Interpolation of Cubic SplinesInterpolation of Cubic Splines
Interpolation of Cubic Splines
 
Les nouveautés de C# 6
Les nouveautés de C# 6Les nouveautés de C# 6
Les nouveautés de C# 6
 
Defining Functions on Equivalence Classes
Defining Functions on Equivalence ClassesDefining Functions on Equivalence Classes
Defining Functions on Equivalence Classes
 
Discrete Sets
Discrete  SetsDiscrete  Sets
Discrete Sets
 
Pre-Cal 40S Slides February 29, 2008
Pre-Cal 40S Slides February 29, 2008Pre-Cal 40S Slides February 29, 2008
Pre-Cal 40S Slides February 29, 2008
 
Functions and graphs
Functions and graphsFunctions and graphs
Functions and graphs
 
Lecture 7 data structures and algorithms
Lecture 7 data structures and algorithmsLecture 7 data structures and algorithms
Lecture 7 data structures and algorithms
 
Daa chapter7
Daa chapter7Daa chapter7
Daa chapter7
 
The Ring programming language version 1.5.3 book - Part 24 of 184
The Ring programming language version 1.5.3 book - Part 24 of 184The Ring programming language version 1.5.3 book - Part 24 of 184
The Ring programming language version 1.5.3 book - Part 24 of 184
 
Blackbox task 2
Blackbox task 2Blackbox task 2
Blackbox task 2
 
Math 4 graphing rational functions
Math 4 graphing rational functionsMath 4 graphing rational functions
Math 4 graphing rational functions
 
Pandas Series
Pandas SeriesPandas Series
Pandas Series
 
On the Design of a Galculator
On the Design of a GalculatorOn the Design of a Galculator
On the Design of a Galculator
 
Kotlin for Android Developers - 2
Kotlin for Android Developers - 2Kotlin for Android Developers - 2
Kotlin for Android Developers - 2
 
Comparisons
ComparisonsComparisons
Comparisons
 
Shape Analysis
Shape AnalysisShape Analysis
Shape Analysis
 
6 slopes and difference quotient x
6 slopes and difference quotient x6 slopes and difference quotient x
6 slopes and difference quotient x
 
List and Dictionary in python
List and Dictionary in pythonList and Dictionary in python
List and Dictionary in python
 
FSharp Talk
FSharp TalkFSharp Talk
FSharp Talk
 
Data Visualization 2020_21
Data Visualization 2020_21Data Visualization 2020_21
Data Visualization 2020_21
 

Destaque

WALA Tutorial at PLDI 2010
WALA Tutorial at PLDI 2010WALA Tutorial at PLDI 2010
WALA Tutorial at PLDI 2010Julian Dolby
 
ISSTA 2010 Presentation
ISSTA 2010 PresentationISSTA 2010 Presentation
ISSTA 2010 PresentationJulian Dolby
 
Using SPARQL Optionals
Using SPARQL OptionalsUsing SPARQL Optionals
Using SPARQL OptionalsJulian Dolby
 
What's Next in Growth? 2016
What's Next in Growth? 2016What's Next in Growth? 2016
What's Next in Growth? 2016Andrew Chen
 
The Outcome Economy
The Outcome EconomyThe Outcome Economy
The Outcome EconomyHelge Tennø
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your BusinessBarry Feldman
 

Destaque (7)

WALA Tutorial at PLDI 2010
WALA Tutorial at PLDI 2010WALA Tutorial at PLDI 2010
WALA Tutorial at PLDI 2010
 
Marathon - RV2011
Marathon - RV2011Marathon - RV2011
Marathon - RV2011
 
ISSTA 2010 Presentation
ISSTA 2010 PresentationISSTA 2010 Presentation
ISSTA 2010 Presentation
 
Using SPARQL Optionals
Using SPARQL OptionalsUsing SPARQL Optionals
Using SPARQL Optionals
 
What's Next in Growth? 2016
What's Next in Growth? 2016What's Next in Growth? 2016
What's Next in Growth? 2016
 
The Outcome Economy
The Outcome EconomyThe Outcome Economy
The Outcome Economy
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
 

Semelhante a Miniatur at FSE 2007

02 Arrays And Memory Mapping
02 Arrays And Memory Mapping02 Arrays And Memory Mapping
02 Arrays And Memory MappingQundeel
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scaladjspiewak
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Review session2
Review session2Review session2
Review session2NEEDY12345
 
CS17604_TOP Parser Compiler Design Techniques
CS17604_TOP Parser Compiler Design TechniquesCS17604_TOP Parser Compiler Design Techniques
CS17604_TOP Parser Compiler Design Techniquesd72994185
 
Scope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesScope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesEelco Visser
 
Revision Tour 1 and 2 complete.doc
Revision Tour 1 and 2 complete.docRevision Tour 1 and 2 complete.doc
Revision Tour 1 and 2 complete.docSrikrishnaVundavalli
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceAlexey Raga
 
Scaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazScaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazHeiko Seeberger
 
Data structure 8.pptx
Data structure 8.pptxData structure 8.pptx
Data structure 8.pptxSajalFayyaz
 

Semelhante a Miniatur at FSE 2007 (20)

02 Arrays And Memory Mapping
02 Arrays And Memory Mapping02 Arrays And Memory Mapping
02 Arrays And Memory Mapping
 
Lecture2
Lecture2Lecture2
Lecture2
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scala
 
Array
ArrayArray
Array
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Review session2
Review session2Review session2
Review session2
 
CS17604_TOP Parser Compiler Design Techniques
CS17604_TOP Parser Compiler Design TechniquesCS17604_TOP Parser Compiler Design Techniques
CS17604_TOP Parser Compiler Design Techniques
 
Scope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languagesScope Graphs: A fresh look at name binding in programming languages
Scope Graphs: A fresh look at name binding in programming languages
 
Revision Tour 1 and 2 complete.doc
Revision Tour 1 and 2 complete.docRevision Tour 1 and 2 complete.doc
Revision Tour 1 and 2 complete.doc
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritance
 
Dynamic Semantics
Dynamic SemanticsDynamic Semantics
Dynamic Semantics
 
Array
ArrayArray
Array
 
Scaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of ScalazScaladays 2011 - The Ease of Scalaz
Scaladays 2011 - The Ease of Scalaz
 
Presentation1.pdf
Presentation1.pdfPresentation1.pdf
Presentation1.pdf
 
Ch8b
Ch8bCh8b
Ch8b
 
Algorithm Exam Help
Algorithm Exam HelpAlgorithm Exam Help
Algorithm Exam Help
 
Data structure 8.pptx
Data structure 8.pptxData structure 8.pptx
Data structure 8.pptx
 
Top down parsing
Top down parsingTop down parsing
Top down parsing
 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
 
Lec9
Lec9Lec9
Lec9
 

Miniatur at FSE 2007

  • 1. Finding Bugs Efficiently with a SAT Solver Julian Dolby, Mandana Vaziri, Frank Tip IBM Thomas J. Watson Research Center FSE 2007—Dubrovnik, Croatia—September 6, 2007
  • 2. Outline • Background • Miniatur Contributions • Example • Miniatur Evaluation • Related Work • Conclusions and Future Work
  • 3. Background—Finding Bugs • Finding bugs must balance coverage and precision – Tools must find bugs to be useful – Tools must minimize false positives to be useful
  • 4. Background—Finding Bugs • Testing approaches find real bugs – Each test is an actual execution, so all bugs real – Coverage depends upon test suite, so often spotty
  • 5. Background—Finding Bugs • Conservative static analysis approaches find all bugs – Conservative approximation of all executions – Can find false positives due to approximation
  • 6. Background—Systematic Underapproximation • Systematic underapproximation blends testing and analysis – Explores all possible concrete execution within a finite set – Real bugs and total coverage within for set of executions
  • 7. Background—Systematic Underapproximation • Key issue is choosing a “good” set of execution – Set must be tractable – Set must cover interesting range of all executions • Use “small scope hypothesis” to bound set of executions – Hypothesis: most data structure bugs need only few objects – E.g. Collection bugs can be seen by inserting few elements – Explore executions with small heaps (also bound loops) (small scope) (other approximation)
  • 8. Background—Finding Bugs with SAT • Given program, specification, find concrete counter example • Use relational first-order logic (FOL) (Alloy [Jackson et al]) – Universe of atoms, and bounded relations over atoms – Relational operators, first-order formulae over relations – Tool (Kodkod[Torlak et al]) translates to CNF for SAT solver • Java in Relational FOL [Vaziri et al] [Taghdiri et al] [Dennis et al] – Heap objects as atoms, types as unary relations – Fields as binary relations, code as formulae – Encode integer operations using bit sets – Solve FOL formula program ∧ ¬(spec)
  • 9. Miniatur Contributions • Supports much larger range of integers than previous work – Integers represented by one atom per power of 2 – Enables e.g. use of hashCode in updating a collection • Novel sparse representation of array objects – Allows subset of array indices to have values – Enables Miniatur to handle array-based collections • Novel sliced translation based on control dependence • General theoretical condition for slicing relational formulae • Demonstration on real collections and a few real programs – Arrays, integers enable analyzing all Java collections – Integers allow checking Java equality contracts
  • 10. Example—HashMap Data class HashMap ... { Entry[] table; ... HashM ap ← {H1} class Entry { Array ← {A1} Object key; Entry ← {E1} Object value; Object ← {A1, E1, H1, K1, V 1} int hash; table ← { H1, A1 } Entry next; ...}} key ← { E1, K1 } value ← { E1, V 1 } hash ← { E1, #65 } I ← { A1, N 1, #5 } V ← { A1, N 1, E1 }
  • 11. Example—HashMap Data class HashMap ... { Entry[] table; ... HashM ap ← {H1} class Entry { Array ← {A1} Object key; Entry ← {E1} Object value; Object ← {A1, E1, H1, K1, V 1} int hash; table ← { H1, A1 } Entry next; ...}} key ← { E1, K1 } value ← { E1, V 1 } hash ← { E1, #1 , E1, #64 } I ← { A1, N 1, #1 , A1, N 1, #4 } V ← { A1, N 1, E1 }
  • 12. Example—HashMap.put public Object put(Object k, Object v) { int h = k.hashCode(); int i = h % table.length; for (Entry e = table[i]; e != null; e = e.next) { ... } modCount++; table[i] = new Entry(h, k, v, table[i]); return null;
  • 13. Example—HashMap.put public Object put(Object k, Object v) { int h = k.hashCode(); int i = h % table.length; for (Entry e = table[i]; e != null; e = e.next) { ... } modCount++; table[i] = new Entry(h, k, v, table[i]); return null;
  • 14. Example—HashMap.put public Object put(Object k, Object v) { int h = k.hashCode(); int i = h % table.length; Entry e = table[i]; if (e != null) { ... e = e.next if (e != null) { ... e = e.next if (e != null) goto end; } } modCount++; table[i] = new Entry(h, k, v, table[i]); return null;
  • 15. Example—HashMap.put public Object put(Object k, Object v) { int h = k.hashCode(); int i = h % table.length; Entry e = table[i]0; if (e != null) { ... e1 = e.next; if (e1 != null) { ... e2 = e1.next; if (e2 != null) goto end; } } modCount1 = modCount0 + 1; table[i]1 = new Entry(h, k, v, table[i]0); return null;
  • 16. Example—HashMap.put public Object put(Object k, Object v) { int h = k.hashCode(); int i = h % table.length; Entry e = table[i]0; if (e != null) { ... e1 = e.next; if (e1 != null) { ... e2 = e1.next; if (e2 != null) goto end; } } modCount1 = modCount0 + 1; table[i]1 = new Entry(h, k, v, table[i]0); A: assert table[i]1.next == null; // perfect hashing return null;
  • 17. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {E[table].x.E[V 1] |sum(E[table].x.E[I1]) = E[i] } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 18. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {E[table].x.E[V 1] |sum(E[table].x.E[I1]) = E[i] } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1}, next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 19. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {{A1} .x.E[V 1] |sum({A1} .x.E[I1]) = 5 } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 20. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {{A1} . {N 1} .E[V 1] |sum({A1} . {N 1} .E[I1]) = 5 } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 21. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {{A1} . {N 1} .E[V 1] |sum({#1, #4}) = 5 } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 22. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {{A1} . {N 1} .E[V 1] |5 = 5 } ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 23. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← E[table[i]].E[next] E[table[i]] ← {E1} ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 24. Expression for assert table[i]1.next == null ¬ (Guard(A) → E[table[i].next == null]) E[table[i].next == null] ← E[table[i].next] = {N ull} E[table[i].next] ← {N ull} E[table[i]] ← {E1} ... sum(x) ← xi ∈x int(xi ) int(j) ← int(#1) ← 1, int(#2) ← 2, int(#4) ← 4, . . . table ← {A1} , next ← { E1, N ull } T 1 ← { A1, N 1 } , i ← 5 I1 ← { A1, N 1, #1 , A1, N 1, #4 } V 1 ← { A1, N 1, E1 }
  • 25. Guard for assert table[i]1.next == null E[e2! = null] = F alse ∨ E[e1! = null] = F alse ∨ E[e! = null] = F alse
  • 26. Evaluation • Miniatur tool embodies our techniques – Uses WALA for control dependence and other analyses – Uses Kodkod to generate CNF – Uses Minisat as backend SAT solver • Evaluated structural assertions in java.util collections – Check that size fields accurately reflect data structure – Use driver that inserts arbitrary objects into collection • Evaluated java equality contracts on open-source codes – (1) reflexive, (2) symmetric, (3) transitive, (4) non-null, – (5) hashCode, (6-9) compareTo properies
  • 27. Evaluation Results: Testing java.util class formula Time (s) Lines LinkedList this.size = |this.header.next∗ − null| 8.2 111 TreeMap this.size = 67.4 12592 |count(this.root.(lef t + right)∗ − null| TreeSet this.m.size = 80.0 12667 |this.m.root.(lef t + right)∗ − null| HashMap this.size = |this.table[].next∗ − null| 30.0 1107 HashSet this.map.size = 34.8 1129 |(this.map.table[].next∗ − null| • Encode correctness of size fields • Check expressive properties against complex collections • Heap size per type, Loop unrolling
  • 28. Evaluation Results: Testing Equals Contracts • Test each property of each equals method using harness public static void equalsTester(Object a, Object b) { if (a.equals(b)) assert b.equals(a); } • Evaluated several common, open-source benchmarks – Antlr, BCEL, Hsqldb, java cup – Found 20 concrete violations (of 2, 3, 5, 6, 7) – Most tests ran within 2 minutes • Bugs illustrated by concrete counter-examples argument a argument b ArrayType3 ArrayType2 type=54304 type=9181 basic type=UninitializedObjectType3 basic type=anonType3 ... ...
  • 29. Related Work • Most-closely related work is checking Java with Alloy – Vaziri et al, Taghdiri et al, Dennis et al – Miniatur handles more of Java, scales better • SATURN checks C using SAT – Uses manually-tailored summaries – Checks less-rich properties – Better scaling than Miniatur • SMT solvers – Mix SAT with theories for arithmetic, arrays, etc – Can prove properties within particular theories – Current SMT solvers less expressive
  • 30. Conclusions and Future Work • Miniatur makes SAT-based checking for Java practical – Extends prior work to better handle integers, arrays – New, sound slicing mechanism for scalability → Handles real properties on real programs → Deep structural properties on real data structures • Future work – Refinement-based approach to unrolling loops – Model concurrency