37
1 Static Analysis Applications Software Analysis © 2007 Jonathan Aldrich 1 PREfix Reading: A Static Analyzer for Finding Dynamic Programming Errors 17-654/17-765 Analysis of Software Artifacts Jonathan Aldrich Static Analysis Applications 2 Software Analysis © 2007 Jonathan Aldrich Lecture Objectives Analyze Microsoft’s PREfix as a practical example of effective static analysis Big Ideas Symbolic execution Path sensitivity Interprocedural analysis

PREfix - Carnegie Mellon University

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: PREfix - Carnegie Mellon University

1

Static Analysis Applications Software Analysis© 2007 Jonathan Aldrich

1

PREfix

Reading: A Static Analyzer for Finding Dynamic Programming Errors

17-654/17-765Analysis of Software ArtifactsJonathan Aldrich

Static Analysis Applications 2Software Analysis© 2007 Jonathan Aldrich

Lecture Objectives

• Analyze Microsoft’s PREfix as a practical example of effective static analysis

• Big Ideas• Symbolic execution• Path sensitivity• Interprocedural analysis

Page 2: PREfix - Carnegie Mellon University

2

Static Analysis Applications 3Software Analysis© 2007 Jonathan Aldrich

Find the Bugs!

char *f(int size) {char * result;if (size > 0)

result = (char *)malloc(size);if (size == 1)

return NULL;result[0] = 0; // result may be uninitialized

return result;}

Static Analysis Applications 4Software Analysis© 2007 Jonathan Aldrich

Find the Bugs!

char *f(int size) {char * result;if (size > 0)

result = (char *)malloc(size);if (size == 1)

return NULL; // memory leakresult[0] = 0; // result may be uninitialized

// malloc may have failedreturn result;

}

Page 3: PREfix - Carnegie Mellon University

3

Static Analysis Applications 5Software Analysis© 2007 Jonathan Aldrich

Motivation

• Finding programming errors• invalid pointers• storage allocation errors• uninitialized memory• improper operations on resources

Static Analysis Applications 6Software Analysis© 2007 Jonathan Aldrich

Can’t we just test?

• 90% of errors involve interactions of multiple functions• Is this why the original developer didn’t find

them?

• Occur in unusual or error conditions• Often hard to exercise with testing

Page 4: PREfix - Carnegie Mellon University

4

Static Analysis Applications 7Software Analysis© 2007 Jonathan Aldrich

Challenges for Analysis

• False Negatives• Looking only in one function and miss

errors across functions

• False Positives• Reporting errors that can’t really occur

• Engineering effort (e.g. ESC/Java)• Requiring extensive program specifications

• Execution overhead• Monitoring program may be impractical• Only as good as your test suite

Static Analysis Applications 8Software Analysis© 2007 Jonathan Aldrich

Goals of PREfix

• Handle hard aspects of C-like languages• Pointers, arrays, unions, libraries, casts…

• Don't require user annotations• Build on language semantics

• Avoid false positives• Use path-sensitive analysis

• Give the user good feedback• Why might an error occur? Show the user

an example execution

Page 5: PREfix - Carnegie Mellon University

5

Static Analysis Applications 9Software Analysis© 2007 Jonathan Aldrich

PREfix Analysis

• Explore paths through function• For each path:

• Symbolically execute path• Determine facts true along the path

• Compute a guard• What must be true for the path to be taken

• Compute constraints• Preconditions for successful execution of path

• Compute result• What is true of the return value?

Static Analysis Applications 10Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

Page 6: PREfix - Carnegie Mellon University

6

Static Analysis Applications 11Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

Static Analysis Applications 12Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

Page 7: PREfix - Carnegie Mellon University

7

Static Analysis Applications 13Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initialized

Static Analysis Applications 14Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size > 0constraint initialized(size)

Page 8: PREfix - Carnegie Mellon University

8

Static Analysis Applications 15Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size > 0constraint initialized(size)fact ptr==memory_new(size)

Static Analysis Applications 16Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)

Page 9: PREfix - Carnegie Mellon University

9

Static Analysis Applications 17Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

Static Analysis Applications 18Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

Page 10: PREfix - Carnegie Mellon University

10

Static Analysis Applications 19Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 0constraint initialized(size)

Static Analysis Applications 20Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 0constraint initialized(size)fact ptr==NULL

Page 11: PREfix - Carnegie Mellon University

11

Static Analysis Applications 21Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

Static Analysis Applications 22Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULL

Page 12: PREfix - Carnegie Mellon University

12

Static Analysis Applications 23Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)

Static Analysis Applications 24Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)

Page 13: PREfix - Carnegie Mellon University

13

Static Analysis Applications 25Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)

Static Analysis Applications 26Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)fact ptr[0] == 0

Page 14: PREfix - Carnegie Mellon University

14

Static Analysis Applications 27Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)fact ptr[0] == 0result return == memory_new(size) && return[0] == 0

Static Analysis Applications 28Software Analysis© 2007 Jonathan Aldrich

PREfix: Analysis Example(syntax slightly de-LISP-ified)

char *f(int size) {char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)fact ptr[0] == 0result return == memory_new(size) && return[0] == 0

alternate 4…

Page 15: PREfix - Carnegie Mellon University

15

Static Analysis Applications 29Software Analysis© 2007 Jonathan Aldrich

Big Ideas

• Symbolic execution• Explore a subset of possible program executions• May not find all errors, but still useful• Carefully constructed to cover more functionality

than most testing strategies can

• Path sensitivity• Avoids reporting errors that occur on control-flow

paths that can’t really be taken

• Interprocedural analysis• Looks at how the behavior of a callee affects the

caller

Static Analysis Applications 30Software Analysis© 2007 Jonathan Aldrich

Motivation: Path Sensitivity

[z := 0]1if [b]2

[z := 10]3;[x := 100]4;if [b]5

[x := x / z]6;

• Does this code have a bug?• What would zero analysis say?

after pp z0 MZ1 Z2 Z3 NZ4 MZ5 MZWarning: possible

divide by zero

MZ

Z NZ

Page 16: PREfix - Carnegie Mellon University

16

Static Analysis Applications 31Software Analysis© 2007 Jonathan Aldrich

Path Sensitive Analysis

[z := 0]1if [b]2

[z := 10]3;[x := 100]4;if [b]5

[x := x / z]6;

Analysis value after statement0: [z↦MZ, b↦unknown]1: [z↦Z, b↦unknown]2: Split path into p and q on b2p: [z↦Z, b↦true], take branch3p: [z↦NZ, b↦true]4p: [z↦NZ, x↦NZ, b↦true]5p: [z↦NZ, x↦NZ, b↦true], take branch6p: [z↦NZ, x↦NZ, b↦true]No error

MZ

Z NZ

unknown

true false

Static Analysis Applications 32Software Analysis© 2007 Jonathan Aldrich

Path Sensitive Analysis

[z := 0]1if [b]2

[z := 10]3;[x := 100]4;if [b]5

[x := x / z]6;

Analysis value after statement0: [z↦MZ, b↦unknown]1: [z↦Z, b↦unknown]2: Split path into p and q on b2q: [z↦Z, b↦false], skip branch

4q: [z↦Z, x↦NZ, b↦false]5q: [z↦Z, x↦NZ, b↦false], skip branch

No error

MZ

Z NZ

unknown

true false

Page 17: PREfix - Carnegie Mellon University

17

Static Analysis Applications 33Software Analysis© 2007 Jonathan Aldrich

Path Sensitive Analysis

Analyzes each feasible program path separately

• Benefit• Increased precision from eliminating infeasible paths

• Cost• Exponential number of paths

• Loops• Infinite number of paths—cannot explore them all

Static Analysis Applications 34Software Analysis© 2007 Jonathan Aldrich

Path Sensitivity:Addressing the Cost

• How does PREfix deal with• Exponential path blowup?

• Explore up to a fixed number of paths• Merge paths with identical results

• Loops?• Explore up to a fixed number of iterations

Page 18: PREfix - Carnegie Mellon University

18

Static Analysis Applications 35Software Analysis© 2007 Jonathan Aldrich

What if you miss a path?char *f(int size) {

char * ptr;if (size > 0)

ptr=(char*)malloc(size);if (size == 1)

return NULL;ptr[0] = 0; return ptr;

}

f (param size)alternate 0

guard size <= 0constraint initialized(size)

ARRAY ACCESS ERROR: ptr not initializedalternate 1

guard size == 1constraint initialized(size)fact ptr==memory_new(size)result return==NULL

MEMORY LEAK ERROR:memory pointed to by ptr is not reachablethrough externally visible state

alternate 2guard size > 1constraint initialized(size)fact ptr==NULL

ARRAY ACCESS ERROR: ptr is NULLalternate 3

guard size > 1constraint initialized(size)fact ptr==memory_new(size)fact ptr[0] == 0result return == memory_new(size) && return[0] == 0

alternate 4…

Static Analysis Applications 36Software Analysis© 2007 Jonathan Aldrich

Soundness for PREfix

• Exploring only some paths is unsound• Might miss bugs on paths not explored

• Sound alternatives• Explore a fixed set of paths/iterations• Merge all other paths together using

dataflow analysis to reach a fixed point• Cost

• May yield too many false positive error reports• PREfix chooses unsoundness to avoid false

positives

Page 19: PREfix - Carnegie Mellon University

19

Static Analysis Applications 37Software Analysis© 2007 Jonathan Aldrich

Motivation:Interprocedural Analysis

void exercise_deref() {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

• Are there errors in this code?

Static Analysis Applications 38Software Analysis© 2007 Jonathan Aldrich

Motivation:Interprocedural Analysis

void exercise_deref() {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

• Are there errors in this code?• Depends on what the function does• Second call: error if dereference w/o NULL check• Third call: error if any dereference

Page 20: PREfix - Carnegie Mellon University

20

Static Analysis Applications 39Software Analysis© 2007 Jonathan Aldrich

Interprocedural Analysis

• Any analysis where the analysis results for a caller depend on the results for a callee, or vice versa

Static Analysis Applications 40Software Analysis© 2007 Jonathan Aldrich

Summaries

• Summarize what a function does• Maps arguments to results• May case-analyze on argument information• Simulateable

• Given information about arguments, will yield:• Any errors• Information about results

Page 21: PREfix - Carnegie Mellon University

21

Static Analysis Applications 41Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Beginderef (param p)

Static Analysis Applications 42Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Use of pderef (param p)

constraint initialized(p)

Page 22: PREfix - Carnegie Mellon University

22

Static Analysis Applications 43Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Split path on value of pderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)

Static Analysis Applications 44Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Return statementderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)result return==NULL

Page 23: PREfix - Carnegie Mellon University

23

Static Analysis Applications 45Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Consider other pathderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)

Static Analysis Applications 46Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Dereference of pderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)

Page 24: PREfix - Carnegie Mellon University

24

Static Analysis Applications 47Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Use of *pderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)

Static Analysis Applications 48Software Analysis© 2007 Jonathan Aldrich

PREfix: Building a Summary(syntax slightly de-LISP-ified)

int deref(int *p) {if (p == NULL)

return NULL;return *p;

}

• Return statementderef (param p)

alternate return_0guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

Page 25: PREfix - Carnegie Mellon University

25

Static Analysis Applications 49Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Beginexercise_deref

Static Analysis Applications 50Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Evaluate v = 5exercise _deref

fact initialized(v), v==5

Page 26: PREfix - Carnegie Mellon University

26

Static Analysis Applications 51Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Evaluate &vexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

Static Analysis Applications 52Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

Page 27: PREfix - Carnegie Mellon University

27

Static Analysis Applications 53Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

• only return_X applies

Static Analysis Applications 54Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

• only return_X applies• constraint initialized(&v) -- PASS

Page 28: PREfix - Carnegie Mellon University

28

Static Analysis Applications 55Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

• only return_X applies• constraint initialized(&v) – PASS• constraint valid_ptr(&v) -- PASS

Static Analysis Applications 56Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)

• only return_X applies• constraint initialized(&v) – PASS• constraint valid_ptr(&v) – PASS• constraint initialized(*&v) – PASS

Page 29: PREfix - Carnegie Mellon University

29

Static Analysis Applications 57Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5

• only return_X applies• constraint initialized(&v) – PASS• constraint valid_ptr(&v) – PASS• constraint initialized(*&v) – PASS• apply result

Static Analysis Applications 58Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5

Page 30: PREfix - Carnegie Mellon University

30

Static Analysis Applications 59Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5

• only return_0 applies

Static Analysis Applications 60Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5

• only return_0 applies• constraint initialized(p) -- PASS

Page 31: PREfix - Carnegie Mellon University

31

Static Analysis Applications 61Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULL

• only return_0 applies• constraint initialized(p) – PASS• apply result

Static Analysis Applications 62Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Evaluate (int *) 5exercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

Page 32: PREfix - Carnegie Mellon University

32

Static Analysis Applications 63Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

Static Analysis Applications 64Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

• return_0 does not apply

Page 33: PREfix - Carnegie Mellon University

33

Static Analysis Applications 65Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

• return_0 does not apply• return_X does apply

Static Analysis Applications 66Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

• return_0 does not apply• return_X does apply

• constraint initialized((int *) 5) –PASS

Page 34: PREfix - Carnegie Mellon University

34

Static Analysis Applications 67Software Analysis© 2007 Jonathan Aldrich

PREfix: Using a Summary(syntax slightly de-LISP-ified)

void exercise_deref(int v) {int v = 5;int x = deref(&v);int y = deref(NULL);int z = deref((int *) 5);

}

deref (param p)alternate return_0

guard p==NULLconstraint initialized(p)result return==NULL

alternate return_Xguard p != NULLconstraint initialized(p)constraint valid_ptr(p)constraint initialized(*p)result return==*p

• Apply summaryexercise _deref

fact initialized(v), v==5fact initialized(&v), valid_ptr(&v)fact x==5fact y==NULLfact !valid_ptr((int *) 5), (int *) 5 != NULL

• return_0 does not apply• return_X does apply

• constraint initialized((int *) 5) – PASS• constraint valid_ptr((int *) 5) –

FAIL• Generate error

Static Analysis Applications 68Software Analysis© 2007 Jonathan Aldrich

PREfix Scaleability

• Analysis cost = 2x-5x build cost• Scales linearly

• Probably due to fixed cutoff on number of paths

Page 35: PREfix - Carnegie Mellon University

35

Static Analysis Applications 69Software Analysis© 2007 Jonathan Aldrich

Value of Interprocedural Analysis

• 90% of errors require models (summaries)

Static Analysis Applications 70Software Analysis© 2007 Jonathan Aldrich

You don’t need every path

• Get most of the warnings with 100 paths

Page 36: PREfix - Carnegie Mellon University

36

Static Analysis Applications 71Software Analysis© 2007 Jonathan Aldrich

Empirical Observations

• PREfix finds errors off the main code paths• Main-path errors caught by careful coding and

testing

• UI is essential• Text output is hard to read• Need tool to visualize paths, sort defect reports

• Noise warnings• Real errors that users don’t care about

• E.g., memory leaks during catastrophic shutdown

Static Analysis Applications 72Software Analysis© 2007 Jonathan Aldrich

PREfix Summary

• PREfix: Great tool to find errors• Can’t guarantee that it finds them all

• Role for other tools• Complements testing by analyzing uncommon

paths• Focuses on low-level errors, not logic/functionality

errors• Role for functional testing

• Huge impact• Used widely within Microsoft• Lightweight version is part of new Visual Studio

Page 37: PREfix - Carnegie Mellon University

37

Static Analysis Applications 73Software Analysis© 2007 Jonathan Aldrich

Further Reading

• William R. Bush, Jonathan D. Pincus, and David J. Sielaff. A Static Analyzer for Finding Dynamic Programming Errors.Software—Practice and Experience, 30:775-802, 2000.