260 likes | 341 Views
Learn how to enhance static analysis to detect null pointer bugs effectively, with insights on bug patterns, risk levels, and solutions for null dereferencing scenarios. Discover ways to fine-tune detectors for low false positives.
E N D
Evaluating and Tuning a Static Analysis to Find Null Pointer Bugs David Hovemeyer, Jaime Spacco, and William Pugh Presented by Nathaniel Ayewah CMSC838P 11/16/2006
Why Simple • Programmers make simple mistakes // org.eclipse.jdt.internal.ui.compare.JavaStructureDiffViewer Control c = getControl(); if (c == null && c.isDisposed()) return; • Low False Positive Rate • Cannot find all bugs
Findbugs INPUT PROCESSING OUTPUT • Set of “.class” files containing byte-code • Configurations • Bug Pattern Code • Source Line Number • Descriptive Message Detectors
Findbugs Detectors PROCESSING • Independent of each other • May share some resources • GOAL: Low false positives • Each detector is driven by a set of heuristics Know Your Bug Patterns
Output HIGH SEVERE RISK OF PROGRAM FAILURE MEDIUM ELEVATED RISK OF PROGRAM FAILURE LOW LOW RISK OF PROGRAM FAILURE Source: US Department of Program Security
Findbugs Detectors PROCESSING Null Pointer Analysis
Null Pointer Analysis PROCESSING • Forward intra-procedural • Build Control Flow graph for each method Slot Method parmeter, local variable, or stack operand Null NonNull Data-flow Frame
Simple Analysis Detector foo = null; foo.execute(); HIGH SEVERE RISK OF PROGRAM FAILURE Dereferencing Null Detector foo = new Detector(…); foo.execute(); Dereferencing NonNull
If only it were that simple… • Is a method’s parameter null? void foo(Object obj) { int x = obj.hashcode(); … } • Infeasible Paths
Infeasible Paths • Guard indirectly connected to null check boolean b; if (p != null) b = true; else b = false; if (b) p.f()
Infeasible Paths • Assertions p = null; ... // throws exception if p null: checkAssertion(p != null); p.f(); // safe
Infeasible Paths • Checked Exceptions that are never thrown Foo dup = null; try { dup = super.clone(); } catch (CloneNotSupportedException e) { // Can’t happen } dup.contents = ...
Solution • Null and NonNull are not enough Checked NonNull No Kaboom NonNull if (b) { A } else { B } C ? NonNull Null-E NCP Null NSP-E NSP
Solution • Dereferencing a variable that has value Null, NSP, … MEDIUM ELEVATED RISK OF PROGRAM FAILURE Null-E … HIGH SEVERE RISK OF PROGRAM FAILURE LOW LOW RISK OF PROGRAM FAILURE Null NSP-E NSP MEDIUM ELEVATED RISK OF PROGRAM FAILURE
Solution • Choosing a value for a variable after each statement: Statement Value of p p = null Null p = this NonNull p = new ... NonNull p = "string" NonNull p = Foo.class NonNull p = q.x NCP p = a[i] NCP p = f() NCP
Solution: Infeasible Paths p = null; Null Null p = new … NonNull Null NSP NCP NCP
Solution: Infeasible Paths Null or NSP checkAssertion(p != null) NCP p.f()
Solution: Infeasible Paths try { } Null NSP catch(Exception e) { } Null-E NSP-E
Comparing a Value to null foo.execute(); if (foo != null) { ... } Comparing No-Kaboom to null HIGH SEVERE RISK OF PROGRAM FAILURE
Comparing a value to null Detector foo = null; if (foo != null) { foo.execute(); } MEDIUM ELEVATED RISK OF PROGRAM FAILURE Comparing Null to null R.I.P if (foo != null) { ... if (foo == null) { foo = new ... } } Comparing Checked NonNull to null MEDIUM ELEVATED RISK OF PROGRAM FAILURE R.I.P
Other Solutions • Check for methods that unconditionally dereference parameters • Annotations • @NotNull: parameter/return value must not be null • @CheckForNull: check the parameter/return value before dereferencing it
Experiments: Student Code • With Annotations
Experiments: Student Code • Without Annotations
Experiments: Production Code • Cannot calc. false negatives! Eclipse 3.0.1
Conclusion • More inter-procedural techniques could find more bugs • But often finding simple bugs with low FP rate is effective