Static Analysis, part 2 Claire Le Goues 2015 (c)
Description: Static Analysis, part 2 Claire Le Goues 2015 (c) C. Le Goues 1 Learning goals Really understand control- and data-flow analysis. Receive a high-level introduction to more formal proving tools. Develop evidence-based recommendations for how
Related Topics
Download Presentation
"Static Analysis, part 2 Claire Le Goues 2015 (c)" is the property of its rightful owner. Permission is granted to download and print the materials on this website for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Presentation Transcript
slide1. Static Analysis, part 2 Claire Le Goues 2015 (c) C. Le Goues 1<br>
slide2. Learning goals Really understand control- and data-flow analysis.
Receive a high-level introduction to more formal proving tools.
Develop evidence-based recommendations for how to deploy analysis tools in your project or organization.
Explain how abstraction applies to dynamic analysis (lightning-fast!). 2 2015 (c) C. Le Goues<br>
slide3. Two fundamental concepts Abstraction
Elide details of a specific implementation.
Capture semantically relevant details; ignore the rest.
Programs as data
Programs are just trees/graphs!
…and CS has lots of ways to analyze trees/graphs 3 2015 (c) C. Le Goues<br>
slide4. What is Static Analysis? Systematic examination of an abstraction of program state space 4 Don’t track everything! (That’s normal interpretation) Ensure everything is checked in the same way 2015 (c) C. Le Goues<br>
slide5. Compare to testing, inspection Why might it be hard to test/inspect for:
Array bounds errors?
Forgetting to re-enable interrupts?
Race conditions? 5 2015 (c) C. Le Goues<br>
slide6. Compare to testing, inspection Array Bounds, Interrupts
Testing
Errors typically on uncommon paths or uncommon input
Difficult to exercise these paths
Inspection
Non-local and thus easy to miss
Array allocation vs. index expression
Disable interrupts vs. return statement
Finding Race Conditions
Testing
Cannot force all interleavings
Inspection
Too many interleavings to consider
Check rules like “lock protects x” instead
But checking is non-local and thus easy to miss a case 6 2015 (c) C. Le Goues<br>
slide7. Defects Static Analysis can Catch Defects that result from inconsistently following simple, mechanical design rules.
Security: Buffer overruns, improperly validated input.
Memory safety: Null dereference, uninitialized data.
Resource leaks: Memory, OS resources.
API Protocols: Device drivers; real time libraries; GUI frameworks.
Exceptions: Arithmetic/library/user-defined
Encapsulation: Accessing internal data, calling private functions.
Data races: Two threads access the same data without synchronization 7 2015 (c) C. Le Goues Key: check compliance to simple, mechanical design rules<br>
slide8. The Bad News: Rice's Theorem Every static analysis is necessarily incomplete or unsound or undecidable (or multiple of these) 8 "Any nontrivial property about the language recognized by a Turing machine is undecidable.“
Henry Gordon Rice, 1953 2015 (c) C. Le Goues<br>
slide9. Results combined 9 Sound Analysis All Defects Complete Analysis Unsound and Incomplete Analysis 2015 (c) C. Le Goues<br>
slide10. Results 10 2015 (c) C. Le Goues What is a violation here? What is a violation here? Sound Analysis Complete Analysis Approximation of
behaviors Approximation of
behaviors<br>
slide11. Continuum of formality Pattern identification (FindBugs, Lint)
Type checking
Dataflow analysis
Model checking
Formal reasoning
Hoare logic
Automated theorem prover 11 2015 (c) C. Le Goues<br>
slide12. Abstract Syntax Trees 12 Program … < block … That is what your IDE and compiler are doing 2015 (c) C. Le Goues<br>
slide13. /* from Linux 2.3.99 drivers/block/raid5.c */
static struct buffer_head *
get_free_buffer(struct stripe_head * sh,
int b_size) {
struct buffer_head *bh;
unsigned long flags;
save_flags(flags);
cli(); // disables interrupts
if ((bh = sh->buffer_pool) == NULL)
return NULL;
sh->buffer_pool = bh -> b_next;
bh->b_size = b_size;
restore_flags(flags); // re-enables interrupts
return bh;
} 13 With thanks to Jonathan Aldrich; example from Engler et al., Checking system rules Using System-Specific, Programmer-Written Compiler Extensions, OSDI ‘000 2015 (c) C. Le Goues<br>
slide14. sm check_interrupts {
// variables; used in patterns
decl { unsigned } flags;
// patterns specify enable/disable functions
pat enable = { sti() ; }
| { restore_flags(flags); } ;
pat disable = { cli() ; }
//states; first state is initial
is_enabled : disable is_disabled
| enable { err(“double enable”); }
;
is_disabled : enable is_enabled
| disable { err(“double disable”); }
//special pattern that matches when
// end of path is reached in this state
| $end_of_path$
{ err(“exiting with inter disabled!”); }
;
} 14 is_enabled is_disabled end path err(exiting with inter disabled) With thanks to Jonathan Aldrich; example from Engler et al., Checking system rules Using System-Specific, Programmer-Written Compiler Extensions, OSDI ‘000 2015 (c) C. Le Goues<br>
slide15. Abstraction void foo() {
…
cli();
if (a) {
restore_flags();
}
} 15 (entry) cli(); if (rv > 0) restore_flags(); (exit) 2015 (c) C. Le Goues<br>
slide16. Dataflow Analysis Example Consider the following program: 16 Use zero analysis to determine if x is ever 0 2015 (c) C. Le Goues<br>
slide17. Applying Zero Analysis 17 y > -1 x = 10 x = x / y (exit) y = y - 1 y = x z = 0 z = 5 17 2015 (c) C. Le Goues<br>
slide18. Applying Zero Analysis 18 y > -1 x = 10 x = x / y (exit) y = y - 1 y = x z = 0 z = 5 18 x:NZ x:NZ, y:NZ x:NZ, y:NZ, z:Z x:NZ, y:NZ, z:Z x:NZ, y:NZ, z:Z x:NZ, y:MZ, z:Z x:NZ, y:MZ, z:NZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:NZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:NZ 2015 (c) C. Le Goues<br>
slide19. Termination Analysis values will not change, no matter how many times loop executes
Proof: our analysis is deterministic
We run through the loop with the current analysis values, none of them change. Therefore, no matter how many times we run the loop, the results will remain the same
Therefore, we have computed the dataflow analysis results for any number of loop iterations 19 Example final result: x:NZ, y:MZ, z:MZ 2015 (c) C. Le Goues<br>
slide20. Abstraction at Work Number of possible states gigantic
n 32 bit variables results in 232*n states
2(32*3) = 296
With loops, states can change indefinitely
Zero Analysis narrows the state space
Zero or not zero
2(2*3) = 26
When this limited space is explored, then we are done
Extrapolate over all loop iterations 20 2015 (c) C. Le Goues<br>
slide21. Exercise time! int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 21 Are there any possible null pointer exceptions in this code? 2015 (c) C. Le Goues<br>
slide22. In graph form… int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
} else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 22 Integer x = new Integer(6); if (y != null) return z + x.intVal(); Integer y = bar(); int z; 2015 (c) C. Le Goues<br>
slide23. Null pointer analysis Track each variable in the program at all program points.
Abstraction:
Program counter
3 states for each variable: null, not-null, and maybe-null.
Then check if, at each dereference, the analysis has identified whether the dereferenced variable is or might be null. 23 2015 (c) C. Le Goues<br>
slide24. In graph form… int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
} else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 24 Integer x = new Integer(6); int z;
if (y != null) return z + x.intVal(); Integer y = bar(); x not-null x not-null, y maybe-null x not-null, y maybe-null x not-null, y maybe-null x not-null, y maybe-null x null, y maybe-null x maybe-null, y maybe-null Error: may have null pointer on line 12, because x may be null! 2015 (c) C. Le Goues<br>
slide25. Continuum of formality Pattern identification (FindBugs, Lint)
Type checking
Dataflow analysis
Model checking
Formal reasoning
Hoare logic
Automated theorem prover 25 2015 (c) C. Le Goues<br>
slide26. Model Checking Build model of a program and exhaustively evaluate that model against a specification
Check properties hold
Produce counter examples
Common form of model checking uses temporal logic formula to describe properties
Especially good for finding concurrency issues
Subject of Thursday’s lecture! 26 2015 (c) C. Le Goues<br>
slide27. Tools: SPIN Model Checker Simple Promela INterpreter
Well established and freely available model checker
Model processes
Verify linear temporal logic properties
We’ll spend considerable time with SPIN later 27 2015 (c) C. Le Goues http://spinroot.com/<br>
slide28. Tools: Microsoft SLAM Statically check Microsoft Windows drivers
Drivers are difficult to test
Uses Counter Example-Guided Abstraction Refinement (CEGAR)
Based on model checking
Refines over-approximations to minimize false positives 28 2015 (c) C. Le Goues http://research.microsoft.com/en-us/projects/slam/ CEGEAR process implemented in SLAM<br>
slide29. Formal Reasoning: Hoare Logic Set of tools for reasoning about the correctness of a computer program
Uses pre and post conditions
The Hoare triple: {P} S {Q}
P and Q are predicates
S is the program
If we start in a state where P is true and execute S, then S will terminate in a state where Q is true 29 2015 (c) C. Le Goues<br>
slide30. Hoare Triples {x=y} x := x + 3 { x = y + 3 }
{x > -1} x := x * 2 + 3 { x > 1}
{ true} x := 5 { x=5} 30 2015 (c) C. Le Goues<br>
slide31. Hoare Logic Hoare logic defines inference rules for program constructs
Assignment
Conditionals
{ P } if x > 0 then y := z else y := -z { y > 5 }
Loops
{P} while B do S {Q}
Using these rules, we can reason about program correctness if we can come up with pre- and post- conditions.
Common technology in safety-critical systems programming, such as code written in SPARK ADA, avionics systems, etc. 31 2015 (c) C. Le Goues<br>
slide32. Tools: ESC/Java Extended Static Checking for Java
Uses the Simplify theorem prover to evaluate each routine in a program
Embedded assertions/annotations
Checker readable comments
Based on the Java Modeling Language (JML)
/*@ requires i > 0 */
public void div(int i, int j) {
return j/i;
} 32 2015 (c) C. Le Goues C. Flanagan, K.R.M. Leino, M. Lillibridge, G. Nelson, J. B. Saxe and R. Stata. Extended static checking for Java<br>
slide33. Annotation Benefits Annotations express design intent
How you intended to achieve a particular quality attribute
e.g. never writing more than N elements to this array
As you add more annotations, you find more errors
Some annotations already built in to Java libraries 33 2015 (c) C. Le Goues<br>
slide34. Upshot: analysis as approximation Analysis must approximate in practice
False positives: may report errors where there are really none
False negatives: may not report errors that really exist
All analysis tools have either false negatives or false positives
Approximation strategy
Find a pattern P for correct code
which is feasible to check (analysis terminates quickly),
covers most correct code in practice (low false positives),
which implies no errors (no false negatives)
Analysis can be pretty good in practice
Many tools have low false positive/negative rates
A sound tool has no false negatives
Never misses an error in a category that it checks 34 2015 (c) C. Le Goues<br>
slide35. Pseudo-summary: analysis is attribute-Specific Analysis is specific to:
A quality attribute (e.g., race condition, buffer overflow, use after free)
A pattern for verifying that attribute (e.g., protect each shared piece of data with a lock, Presburger arithmetic decision procedure for array indexes, only one variable points to each memory location)
Analysis is inappropriate for some attributes.
For every technique, think about: what’s being abstracted, what data is being lost, where the error can come from!
And maybe: how we can make it better? 35 2015 (c) C. Le Goues<br>
slide36. Why do Static Analysis 36 2015 (c) C. Le Goues<br>
slide37. Quality assurance at Microsoft Original process: manual code inspection
Effective when system and team are small
Too many paths to consider as system grew
Early 1990s: add massive system and unit testing
Tests took weeks to run
Diversity of platforms and configurations
Sheer volume of tests
Inefficient detection of common patterns, security holes
Non-local, intermittent, uncommon path bugsWas treading water in Windows Vista development
Early 2000s: add static analysis 37 2015 (c) C. Le Goues<br>
slide38. Impact at Microsoft Thousands of bugs caught monthly
Significant observed quality improvements
e.g. buffer overruns latent in codebases
Widespread developer acceptance
Check-in gates
Writing specifications 38 2015 (c) C. Le Goues<br>
slide39. Ebay: Prior Evaluations Individual teams tried tools
On snapshots
No tool customization
Overall negative results
Developers were not impressed: many minor issues (2 checkers reported half the issues, all irrelevant for Ebay)
Would this change when integrated into process? i.e. incremental checking
Which bugs to look at? 39 2015 (c) C. Le Goues Jaspan, Ciera, I. Chen, and Anoop Sharma. "Understanding the value of program analysis tools." Companion to the 22nd ACM SIGPLAN conference on Object-oriented programming systems and applications companion. ACM, 2007.<br>
slide40. Ebay: Goals Find defects earlier in the lifecycle
Allow quality engineers to focus on different issues
Find defects that are difficult to find through other QA techniques
security, performance, concurrency
As early as feasible: Run on developer machines and in nightly builds
No resources to build own tool
But few people for dedicated team (customization, policies, creating project-specific analyses etc) possible
Continuous evaluation 40 2015 (c) C. Le Goues<br>
slide41. Ebay: Customization Customization dropped false positives from 50% to 10%
Separate checkers evaluated separately
By number of issues
By severity as judged by developers; iteratively with several groups
Some low-priority checkers (e.g., dead store to local) was assigned high priority – performance impact important for Ebay 41 2015 (c) C. Le Goues<br>
slide42. Ebay: Enforcement policy High priority: All these issues must be fixed (e.g. null pointer exceptions)
Potentially very costly given the huge existing code base
Medium priority: May not be added to the code base. Old issues won't be fixed unless refactored anyway (e.g., high cyclomatic complexity)
Low priority: At most X issues may be added between releases (usually stylistic)
Tossed: Turned off entirely 42 2015 (c) C. Le Goues<br>
slide43. Ebay: Cost estimation Free tool
2 developers full time for customization and extension
A typical tester at ebay finds 10 bugs/week, 10% high priority
Sample bugs found with Findbugs for a comparison 43 2015 (c) C. Le Goues<br>
slide44. Aside: Cost/benefit analysis Cost/Benefit tradeoff
Benefit: How valuable is the bug?
How much does it cost if not found?
How expensive to find using testing/inspection?
Cost: How much did the analysis cost?
Effort spent running analysis, interpreting results – includes false positives
Effort spent finding remaining bugs (for unsound analysis)
Rule of thumb
For critical bugs that testing/inspection can’t find, a sound analysis is worth it, as long as false positive rate is acceptable.
For other bugs, maximize engineer productivity 44 2015 (c) C. Le Goues<br>
slide45. Ebay: Combining tools Program analysis coverage
Performance – High importance
Security – High
Global quality – High
Local quality – medium
API/framework compliance – medium
Concurrency – low
Style and readability – low
Select appropriate tools and detectors 45 2015 (c) C. Le Goues<br>
slide46. Ebay: Enforcement Enforcement at dev/QA handoff:
Developers run FindBugs on desktop
QA runs FindBugs on receipt of code, posts results, require high-priority fixes. 46 2015 (c) C. Le Goues<br>
slide47. Ebay: Continuous evaluation Gather data on detected bugs and false positives
Present to developers, make case for tool 47 2015 (c) C. Le Goues<br>
slide48. Incremental introduction Begin with early adopters in small team
Use these as champions in organization
Support team: answer questions, help with tool. 48 2015 (c) C. Le Goues<br>
slide49. Empirical results Nortel study [Zheng et al. 2006]
3 C/C++ projects
3 million LOC total
Early generation static analysis tools
Conclusions
Cost per fault of static analysis 61-72% compared to inspections
Effectively finds assignment, checking faults
Can be used to find potential security vulnerabilities 49 2015 (c) C. Le Goues<br>
slide50. More empirical results InfoSys study [Chaturvedi 2005]
5 projects
Average 700 function points each
Compare inspection with and without static analysis
Conclusions
Higher productivity
Fewer defects 50 2015 (c) C. Le Goues<br>
slide51. How is test suite coverage computed? Question time! 2015 (c) C. Le Goues 51<br>
slide52. Dynamic analysis Learn about a program’s properties by executing it.
How can we learn about properties that are more interesting than “did this test pass”? (e.g., memory use).
Short answer: examine program state throughout execution by gathering additional information. 52 2015 (c) C. Le Goues<br>
slide53. Common dynamic analysis Coverage
Performance
Memory usage
Security properties
Concurrency errors
Invariant detection 53 2015 (c) C. Le Goues<br>
slide54. Collecting execution info Instrument at compile time
e.g., Aspects, logging
Run on a specialized VM, like valgrind
Instrument or monitor at runtime
Also requires a special VM
E.g., VisualVM (hooks into JVM using debug symbols to profile/monitor) 54 2015 (c) C. Le Goues<br>
slide55. Quick note Some of those require a static pre-processing step, such as inserting logging statements!
It’s still a dynamic analysis, because you run the program, collect the info, and learn from that information. 55 2015 (c) C. Le Goues<br>
slide56. Parts of a dynamic analysis. Property of interest.
Information related to property of interest.
Mechanism for collecting that information from a program execution.
Test input data.
Mechanism for learning about the property of interest from the information you collected. 56 2015 (c) C. Le Goues<br>
slide57. Abstraction How is abstraction relevant to static analysis, again?
Dynamic analysis also requires abstraction.
You’re still focusing on a particular program property or type of information.
Abstracting parts of a trace of exeuction rather than the entire state space. 57 2015 (c) C. Le Goues<br>
slide58. Challenges: Very input dependent Good if you have alots of tests! (system tests are also best)
Are those tests indicative of common behavior?
Is that what you want?
Can also use logs from live sessions (sometimes).
Or specific inputs that replicate specific defect scenarios (like memory leaks). 58 2015 (c) C. Le Goues<br>
slide59. Challenges: Heisenbuggy behavior Instrumentation and monitoring can change the behavior of a program.
E.g., slowdown, overhead
Important question 1: can/should you deploy it live? Or just for debugging something specific?
Important question 2: will the monitoring meaningfully change the program behavior with respect ot the property you care about? 59 2015 (c) C. Le Goues<br>
slide60. Too much data Logging events in large and/or long-running programs (even for just one property!) can result in HUGE amounts of data.
How do you process it?
Common strategy: sampling. 60 2015 (c) C. Le Goues<br>
slide61. Benefits over static analysis Precise data for a specific run.
No false positives or negatives on a given run.
No confusion about which path was taken; it’s clear where an error happened.
Can (often) use on live code.
Very common for security and data gathering. 61 2015 (c) C. Le Goues<br>
slide62. Comparison Static analysis Analyze code without executing it.
Systematically follow an abstraction.
Find bugs/enforce specifications/prove correctness.
Often correctness/security related. Dynamic analysis Analyze specific executions.
Instrument program, or use a special interpreter.
Abstract parts of the trace.
Find bugs/enforce stronger specifications/debugging/profiling.
Often memory/performance/concurrency/security related. 2015 (c) C. Le Goues 62<br>
slide63. Learning goals Really understand control- and data-flow analysis.
Receive a high-level introduction to more formal proving tools.
Develop evidence-based recommendations for how to deploy analysis tools in your project or organization.
Explain the parts of and how abstraction applies to dynamic analysis (lightning-fast!). 63 2015 (c) C. Le Goues<br>
slide2. Learning goals Really understand control- and data-flow analysis.
Receive a high-level introduction to more formal proving tools.
Develop evidence-based recommendations for how to deploy analysis tools in your project or organization.
Explain how abstraction applies to dynamic analysis (lightning-fast!). 2 2015 (c) C. Le Goues<br>
slide3. Two fundamental concepts Abstraction
Elide details of a specific implementation.
Capture semantically relevant details; ignore the rest.
Programs as data
Programs are just trees/graphs!
…and CS has lots of ways to analyze trees/graphs 3 2015 (c) C. Le Goues<br>
slide4. What is Static Analysis? Systematic examination of an abstraction of program state space 4 Don’t track everything! (That’s normal interpretation) Ensure everything is checked in the same way 2015 (c) C. Le Goues<br>
slide5. Compare to testing, inspection Why might it be hard to test/inspect for:
Array bounds errors?
Forgetting to re-enable interrupts?
Race conditions? 5 2015 (c) C. Le Goues<br>
slide6. Compare to testing, inspection Array Bounds, Interrupts
Testing
Errors typically on uncommon paths or uncommon input
Difficult to exercise these paths
Inspection
Non-local and thus easy to miss
Array allocation vs. index expression
Disable interrupts vs. return statement
Finding Race Conditions
Testing
Cannot force all interleavings
Inspection
Too many interleavings to consider
Check rules like “lock protects x” instead
But checking is non-local and thus easy to miss a case 6 2015 (c) C. Le Goues<br>
slide7. Defects Static Analysis can Catch Defects that result from inconsistently following simple, mechanical design rules.
Security: Buffer overruns, improperly validated input.
Memory safety: Null dereference, uninitialized data.
Resource leaks: Memory, OS resources.
API Protocols: Device drivers; real time libraries; GUI frameworks.
Exceptions: Arithmetic/library/user-defined
Encapsulation: Accessing internal data, calling private functions.
Data races: Two threads access the same data without synchronization 7 2015 (c) C. Le Goues Key: check compliance to simple, mechanical design rules<br>
slide8. The Bad News: Rice's Theorem Every static analysis is necessarily incomplete or unsound or undecidable (or multiple of these) 8 "Any nontrivial property about the language recognized by a Turing machine is undecidable.“
Henry Gordon Rice, 1953 2015 (c) C. Le Goues<br>
slide9. Results combined 9 Sound Analysis All Defects Complete Analysis Unsound and Incomplete Analysis 2015 (c) C. Le Goues<br>
slide10. Results 10 2015 (c) C. Le Goues What is a violation here? What is a violation here? Sound Analysis Complete Analysis Approximation of
behaviors Approximation of
behaviors<br>
slide11. Continuum of formality Pattern identification (FindBugs, Lint)
Type checking
Dataflow analysis
Model checking
Formal reasoning
Hoare logic
Automated theorem prover 11 2015 (c) C. Le Goues<br>
slide12. Abstract Syntax Trees 12 Program … < block … That is what your IDE and compiler are doing 2015 (c) C. Le Goues<br>
slide13. /* from Linux 2.3.99 drivers/block/raid5.c */
static struct buffer_head *
get_free_buffer(struct stripe_head * sh,
int b_size) {
struct buffer_head *bh;
unsigned long flags;
save_flags(flags);
cli(); // disables interrupts
if ((bh = sh->buffer_pool) == NULL)
return NULL;
sh->buffer_pool = bh -> b_next;
bh->b_size = b_size;
restore_flags(flags); // re-enables interrupts
return bh;
} 13 With thanks to Jonathan Aldrich; example from Engler et al., Checking system rules Using System-Specific, Programmer-Written Compiler Extensions, OSDI ‘000 2015 (c) C. Le Goues<br>
slide14. sm check_interrupts {
// variables; used in patterns
decl { unsigned } flags;
// patterns specify enable/disable functions
pat enable = { sti() ; }
| { restore_flags(flags); } ;
pat disable = { cli() ; }
//states; first state is initial
is_enabled : disable is_disabled
| enable { err(“double enable”); }
;
is_disabled : enable is_enabled
| disable { err(“double disable”); }
//special pattern that matches when
// end of path is reached in this state
| $end_of_path$
{ err(“exiting with inter disabled!”); }
;
} 14 is_enabled is_disabled end path err(exiting with inter disabled) With thanks to Jonathan Aldrich; example from Engler et al., Checking system rules Using System-Specific, Programmer-Written Compiler Extensions, OSDI ‘000 2015 (c) C. Le Goues<br>
slide15. Abstraction void foo() {
…
cli();
if (a) {
restore_flags();
}
} 15 (entry) cli(); if (rv > 0) restore_flags(); (exit) 2015 (c) C. Le Goues<br>
slide16. Dataflow Analysis Example Consider the following program: 16 Use zero analysis to determine if x is ever 0 2015 (c) C. Le Goues<br>
slide17. Applying Zero Analysis 17 y > -1 x = 10 x = x / y (exit) y = y - 1 y = x z = 0 z = 5 17 2015 (c) C. Le Goues<br>
slide18. Applying Zero Analysis 18 y > -1 x = 10 x = x / y (exit) y = y - 1 y = x z = 0 z = 5 18 x:NZ x:NZ, y:NZ x:NZ, y:NZ, z:Z x:NZ, y:NZ, z:Z x:NZ, y:NZ, z:Z x:NZ, y:MZ, z:Z x:NZ, y:MZ, z:NZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:NZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:MZ x:NZ, y:MZ, z:NZ 2015 (c) C. Le Goues<br>
slide19. Termination Analysis values will not change, no matter how many times loop executes
Proof: our analysis is deterministic
We run through the loop with the current analysis values, none of them change. Therefore, no matter how many times we run the loop, the results will remain the same
Therefore, we have computed the dataflow analysis results for any number of loop iterations 19 Example final result: x:NZ, y:MZ, z:MZ 2015 (c) C. Le Goues<br>
slide20. Abstraction at Work Number of possible states gigantic
n 32 bit variables results in 232*n states
2(32*3) = 296
With loops, states can change indefinitely
Zero Analysis narrows the state space
Zero or not zero
2(2*3) = 26
When this limited space is explored, then we are done
Extrapolate over all loop iterations 20 2015 (c) C. Le Goues<br>
slide21. Exercise time! int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 21 Are there any possible null pointer exceptions in this code? 2015 (c) C. Le Goues<br>
slide22. In graph form… int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
} else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 22 Integer x = new Integer(6); if (y != null) return z + x.intVal(); Integer y = bar(); int z; 2015 (c) C. Le Goues<br>
slide23. Null pointer analysis Track each variable in the program at all program points.
Abstraction:
Program counter
3 states for each variable: null, not-null, and maybe-null.
Then check if, at each dereference, the analysis has identified whether the dereferenced variable is or might be null. 23 2015 (c) C. Le Goues<br>
slide24. In graph form… int foo() {
Integer x = new Integer(6);
Integer y = bar();
int z;
if (y != null)
z = x.intVal() + y.intVal();
} else {
z = x.intVal();
y = x;
x = null;
}
return z + x.intVal();
} 24 Integer x = new Integer(6); int z;
if (y != null) return z + x.intVal(); Integer y = bar(); x not-null x not-null, y maybe-null x not-null, y maybe-null x not-null, y maybe-null x not-null, y maybe-null x null, y maybe-null x maybe-null, y maybe-null Error: may have null pointer on line 12, because x may be null! 2015 (c) C. Le Goues<br>
slide25. Continuum of formality Pattern identification (FindBugs, Lint)
Type checking
Dataflow analysis
Model checking
Formal reasoning
Hoare logic
Automated theorem prover 25 2015 (c) C. Le Goues<br>
slide26. Model Checking Build model of a program and exhaustively evaluate that model against a specification
Check properties hold
Produce counter examples
Common form of model checking uses temporal logic formula to describe properties
Especially good for finding concurrency issues
Subject of Thursday’s lecture! 26 2015 (c) C. Le Goues<br>
slide27. Tools: SPIN Model Checker Simple Promela INterpreter
Well established and freely available model checker
Model processes
Verify linear temporal logic properties
We’ll spend considerable time with SPIN later 27 2015 (c) C. Le Goues http://spinroot.com/<br>
slide28. Tools: Microsoft SLAM Statically check Microsoft Windows drivers
Drivers are difficult to test
Uses Counter Example-Guided Abstraction Refinement (CEGAR)
Based on model checking
Refines over-approximations to minimize false positives 28 2015 (c) C. Le Goues http://research.microsoft.com/en-us/projects/slam/ CEGEAR process implemented in SLAM<br>
slide29. Formal Reasoning: Hoare Logic Set of tools for reasoning about the correctness of a computer program
Uses pre and post conditions
The Hoare triple: {P} S {Q}
P and Q are predicates
S is the program
If we start in a state where P is true and execute S, then S will terminate in a state where Q is true 29 2015 (c) C. Le Goues<br>
slide30. Hoare Triples {x=y} x := x + 3 { x = y + 3 }
{x > -1} x := x * 2 + 3 { x > 1}
{ true} x := 5 { x=5} 30 2015 (c) C. Le Goues<br>
slide31. Hoare Logic Hoare logic defines inference rules for program constructs
Assignment
Conditionals
{ P } if x > 0 then y := z else y := -z { y > 5 }
Loops
{P} while B do S {Q}
Using these rules, we can reason about program correctness if we can come up with pre- and post- conditions.
Common technology in safety-critical systems programming, such as code written in SPARK ADA, avionics systems, etc. 31 2015 (c) C. Le Goues<br>
slide32. Tools: ESC/Java Extended Static Checking for Java
Uses the Simplify theorem prover to evaluate each routine in a program
Embedded assertions/annotations
Checker readable comments
Based on the Java Modeling Language (JML)
/*@ requires i > 0 */
public void div(int i, int j) {
return j/i;
} 32 2015 (c) C. Le Goues C. Flanagan, K.R.M. Leino, M. Lillibridge, G. Nelson, J. B. Saxe and R. Stata. Extended static checking for Java<br>
slide33. Annotation Benefits Annotations express design intent
How you intended to achieve a particular quality attribute
e.g. never writing more than N elements to this array
As you add more annotations, you find more errors
Some annotations already built in to Java libraries 33 2015 (c) C. Le Goues<br>
slide34. Upshot: analysis as approximation Analysis must approximate in practice
False positives: may report errors where there are really none
False negatives: may not report errors that really exist
All analysis tools have either false negatives or false positives
Approximation strategy
Find a pattern P for correct code
which is feasible to check (analysis terminates quickly),
covers most correct code in practice (low false positives),
which implies no errors (no false negatives)
Analysis can be pretty good in practice
Many tools have low false positive/negative rates
A sound tool has no false negatives
Never misses an error in a category that it checks 34 2015 (c) C. Le Goues<br>
slide35. Pseudo-summary: analysis is attribute-Specific Analysis is specific to:
A quality attribute (e.g., race condition, buffer overflow, use after free)
A pattern for verifying that attribute (e.g., protect each shared piece of data with a lock, Presburger arithmetic decision procedure for array indexes, only one variable points to each memory location)
Analysis is inappropriate for some attributes.
For every technique, think about: what’s being abstracted, what data is being lost, where the error can come from!
And maybe: how we can make it better? 35 2015 (c) C. Le Goues<br>
slide36. Why do Static Analysis 36 2015 (c) C. Le Goues<br>
slide37. Quality assurance at Microsoft Original process: manual code inspection
Effective when system and team are small
Too many paths to consider as system grew
Early 1990s: add massive system and unit testing
Tests took weeks to run
Diversity of platforms and configurations
Sheer volume of tests
Inefficient detection of common patterns, security holes
Non-local, intermittent, uncommon path bugsWas treading water in Windows Vista development
Early 2000s: add static analysis 37 2015 (c) C. Le Goues<br>
slide38. Impact at Microsoft Thousands of bugs caught monthly
Significant observed quality improvements
e.g. buffer overruns latent in codebases
Widespread developer acceptance
Check-in gates
Writing specifications 38 2015 (c) C. Le Goues<br>
slide39. Ebay: Prior Evaluations Individual teams tried tools
On snapshots
No tool customization
Overall negative results
Developers were not impressed: many minor issues (2 checkers reported half the issues, all irrelevant for Ebay)
Would this change when integrated into process? i.e. incremental checking
Which bugs to look at? 39 2015 (c) C. Le Goues Jaspan, Ciera, I. Chen, and Anoop Sharma. "Understanding the value of program analysis tools." Companion to the 22nd ACM SIGPLAN conference on Object-oriented programming systems and applications companion. ACM, 2007.<br>
slide40. Ebay: Goals Find defects earlier in the lifecycle
Allow quality engineers to focus on different issues
Find defects that are difficult to find through other QA techniques
security, performance, concurrency
As early as feasible: Run on developer machines and in nightly builds
No resources to build own tool
But few people for dedicated team (customization, policies, creating project-specific analyses etc) possible
Continuous evaluation 40 2015 (c) C. Le Goues<br>
slide41. Ebay: Customization Customization dropped false positives from 50% to 10%
Separate checkers evaluated separately
By number of issues
By severity as judged by developers; iteratively with several groups
Some low-priority checkers (e.g., dead store to local) was assigned high priority – performance impact important for Ebay 41 2015 (c) C. Le Goues<br>
slide42. Ebay: Enforcement policy High priority: All these issues must be fixed (e.g. null pointer exceptions)
Potentially very costly given the huge existing code base
Medium priority: May not be added to the code base. Old issues won't be fixed unless refactored anyway (e.g., high cyclomatic complexity)
Low priority: At most X issues may be added between releases (usually stylistic)
Tossed: Turned off entirely 42 2015 (c) C. Le Goues<br>
slide43. Ebay: Cost estimation Free tool
2 developers full time for customization and extension
A typical tester at ebay finds 10 bugs/week, 10% high priority
Sample bugs found with Findbugs for a comparison 43 2015 (c) C. Le Goues<br>
slide44. Aside: Cost/benefit analysis Cost/Benefit tradeoff
Benefit: How valuable is the bug?
How much does it cost if not found?
How expensive to find using testing/inspection?
Cost: How much did the analysis cost?
Effort spent running analysis, interpreting results – includes false positives
Effort spent finding remaining bugs (for unsound analysis)
Rule of thumb
For critical bugs that testing/inspection can’t find, a sound analysis is worth it, as long as false positive rate is acceptable.
For other bugs, maximize engineer productivity 44 2015 (c) C. Le Goues<br>
slide45. Ebay: Combining tools Program analysis coverage
Performance – High importance
Security – High
Global quality – High
Local quality – medium
API/framework compliance – medium
Concurrency – low
Style and readability – low
Select appropriate tools and detectors 45 2015 (c) C. Le Goues<br>
slide46. Ebay: Enforcement Enforcement at dev/QA handoff:
Developers run FindBugs on desktop
QA runs FindBugs on receipt of code, posts results, require high-priority fixes. 46 2015 (c) C. Le Goues<br>
slide47. Ebay: Continuous evaluation Gather data on detected bugs and false positives
Present to developers, make case for tool 47 2015 (c) C. Le Goues<br>
slide48. Incremental introduction Begin with early adopters in small team
Use these as champions in organization
Support team: answer questions, help with tool. 48 2015 (c) C. Le Goues<br>
slide49. Empirical results Nortel study [Zheng et al. 2006]
3 C/C++ projects
3 million LOC total
Early generation static analysis tools
Conclusions
Cost per fault of static analysis 61-72% compared to inspections
Effectively finds assignment, checking faults
Can be used to find potential security vulnerabilities 49 2015 (c) C. Le Goues<br>
slide50. More empirical results InfoSys study [Chaturvedi 2005]
5 projects
Average 700 function points each
Compare inspection with and without static analysis
Conclusions
Higher productivity
Fewer defects 50 2015 (c) C. Le Goues<br>
slide51. How is test suite coverage computed? Question time! 2015 (c) C. Le Goues 51<br>
slide52. Dynamic analysis Learn about a program’s properties by executing it.
How can we learn about properties that are more interesting than “did this test pass”? (e.g., memory use).
Short answer: examine program state throughout execution by gathering additional information. 52 2015 (c) C. Le Goues<br>
slide53. Common dynamic analysis Coverage
Performance
Memory usage
Security properties
Concurrency errors
Invariant detection 53 2015 (c) C. Le Goues<br>
slide54. Collecting execution info Instrument at compile time
e.g., Aspects, logging
Run on a specialized VM, like valgrind
Instrument or monitor at runtime
Also requires a special VM
E.g., VisualVM (hooks into JVM using debug symbols to profile/monitor) 54 2015 (c) C. Le Goues<br>
slide55. Quick note Some of those require a static pre-processing step, such as inserting logging statements!
It’s still a dynamic analysis, because you run the program, collect the info, and learn from that information. 55 2015 (c) C. Le Goues<br>
slide56. Parts of a dynamic analysis. Property of interest.
Information related to property of interest.
Mechanism for collecting that information from a program execution.
Test input data.
Mechanism for learning about the property of interest from the information you collected. 56 2015 (c) C. Le Goues<br>
slide57. Abstraction How is abstraction relevant to static analysis, again?
Dynamic analysis also requires abstraction.
You’re still focusing on a particular program property or type of information.
Abstracting parts of a trace of exeuction rather than the entire state space. 57 2015 (c) C. Le Goues<br>
slide58. Challenges: Very input dependent Good if you have alots of tests! (system tests are also best)
Are those tests indicative of common behavior?
Is that what you want?
Can also use logs from live sessions (sometimes).
Or specific inputs that replicate specific defect scenarios (like memory leaks). 58 2015 (c) C. Le Goues<br>
slide59. Challenges: Heisenbuggy behavior Instrumentation and monitoring can change the behavior of a program.
E.g., slowdown, overhead
Important question 1: can/should you deploy it live? Or just for debugging something specific?
Important question 2: will the monitoring meaningfully change the program behavior with respect ot the property you care about? 59 2015 (c) C. Le Goues<br>
slide60. Too much data Logging events in large and/or long-running programs (even for just one property!) can result in HUGE amounts of data.
How do you process it?
Common strategy: sampling. 60 2015 (c) C. Le Goues<br>
slide61. Benefits over static analysis Precise data for a specific run.
No false positives or negatives on a given run.
No confusion about which path was taken; it’s clear where an error happened.
Can (often) use on live code.
Very common for security and data gathering. 61 2015 (c) C. Le Goues<br>
slide62. Comparison Static analysis Analyze code without executing it.
Systematically follow an abstraction.
Find bugs/enforce specifications/prove correctness.
Often correctness/security related. Dynamic analysis Analyze specific executions.
Instrument program, or use a special interpreter.
Abstract parts of the trace.
Find bugs/enforce stronger specifications/debugging/profiling.
Often memory/performance/concurrency/security related. 2015 (c) C. Le Goues 62<br>
slide63. Learning goals Really understand control- and data-flow analysis.
Receive a high-level introduction to more formal proving tools.
Develop evidence-based recommendations for how to deploy analysis tools in your project or organization.
Explain the parts of and how abstraction applies to dynamic analysis (lightning-fast!). 63 2015 (c) C. Le Goues<br>