finding bugs that matter with findbugs

52
1 FindBugs™ - Find Bugs in Java Programs Defective Java Code Learning from mistakes Carol McDonald

Upload: carol-mcdonald

Post on 17-May-2015

2.216 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: Finding bugs that matter with Findbugs

1

FindBugs™ - Find Bugs in Java Programs

Defective Java Code

Learning from mistakes

Carol McDonald

Page 2: Finding bugs that matter with Findbugs

2

What is FindBugs?

• Static analysis tool

• Looks for defects based on bug patterns

• Bug patterns come from real bugs

• bug patterns are grouped into categories:

• correctness, bad practice, performance…

• assigned a priority: high, medium or low.

• High-Medium priority have low false positive rates

• http://findbugs.sourceforge.net/

Page 3: Finding bugs that matter with Findbugs

3© Availity, LLC | All rights reserved. 3

Bug Patterns

• broad and common patterns:• a read or write on a null pointer• typos• Methods whose return value should not be

ignored• Also specific bug patterns:

• Every Programming Puzzler• Eclipse documented bug fixes• Every chapter in Effective Java• Many postings to http://thedailywtf.com/

Page 4: Finding bugs that matter with Findbugs

4© Availity, LLC | All rights reserved. 4

Bug Patterns: http://thedailywtf.com/

Page 5: Finding bugs that matter with Findbugs

5© Availity, LLC | All rights reserved.

CN Cloneable Not Implemented Correctly

DC Double Checked Locking

DE Dropped Exception

EC Suspicious Equals Comparison

Eq Bad Covariant Definition of Equals

HE Equal objects must have equal hashcodes

IS2 Inconsistent Synchronization

MS Static Field Modifiable By Untrusted Code

NP Null Pointer Dereference

NS Non-Short-Circuit Boolean Operator

OS Open Stream

RCN Redundant Comparison to Null

RR Read Return Should Be Checked

RV Return Value Should Be Checked

Se Non-serializable Serializable Class

UR Uninitialized Read In Constructor

UW Unconditional Wait

Wa Wait Not In Loop

SomebugPatterns:

Page 6: Finding bugs that matter with Findbugs

6© Availity, LLC | All rights reserved.

SomebugPatterns:

Page 7: Finding bugs that matter with Findbugs

7

Misconceptions about Bugs

• Programmers are smart

• Smart people don’t make dumb mistakes

• WRONG!

• Smart people make dumb mistakes

• Common errors:

• wrong boolean operator, forgetting parentheses, etc.

• Misunderstood class or method !

Page 8: Finding bugs that matter with Findbugs

8

Can you find the Bug?

if (listeners == null)

listeners.remove(listener);

JDK1.6.0, b105, sun.awt.x11.XMSelection

Page 9: Finding bugs that matter with Findbugs

9

Who uses FindBugs?

• Developed from Research at University of Maryland

• Google, Ebay, Sun, Wells Fargo…

• Bill Pugh spent a year sabbatical at Google working Findbugs into their development process

• Google runs FindBugs over all Java code

• 1800s issues identified, > 600 fixed.

• Ebay found 2 developers reviewing Findbugs was 10 times more effective than 2 testers

Page 10: Finding bugs that matter with Findbugs

10

Some Bug Categories

• Correctness - the code is doing something wrong, you should look at it

• Bad practice - the code violates good practice

• Dodgy Code

• Concurrency

• Performance

• Security defect

Page 11: Finding bugs that matter with Findbugs

11

Can you find the Bug?

public String sendMessage (User user, String body, Date time) {

return sendMessage(user, body, null);

}

public String sendMessage (User user, String body, Date time, List attachments) {

String xml = buildXML (body, attachments);

String response = sendMessage(user, xml);

return response;

}

Page 12: Finding bugs that matter with Findbugs

12

Infinite recursive loopHigh priority correctness

public String sendMessage (User user, String body, Date time) {

return sendMessage(user, body, null);

}

public String sendMessage (User user, String body, Date time, List attachments) {

String xml = buildXML (body, attachments);

String response = sendMessage(user, xml);

return response;

}

Page 13: Finding bugs that matter with Findbugs

13

Can you find the Bug?

public String foundType() { return this.foundType();}

Page 14: Finding bugs that matter with Findbugs

14

Infinite recursive loop

public String foundType() { return this.foundType();}// should be public String foundType() { return this.foundType;}

• Findbugs found 5 infinite recursive loops in JDK1.6.0-b13

• Including this one written by Joshua Bloch• Smart people make dumb mistakes

• 27 across all versions of JDK, 31 in Google’s Java code

• Embrace and fix your dumb mistakes

Page 15: Finding bugs that matter with Findbugs

15

Can you find the Bug?

if (name != null || name.length > 0)

Page 16: Finding bugs that matter with Findbugs

16

Can you find the Bug?

if (name != null || name.length > 0)

if (name != null && name.length > 0)

Found in //com.sun.corba.se.impl.naming.cosnaming.NamingContextImpl

Page 17: Finding bugs that matter with Findbugs

17

Can you find the Bug?

if (part == null | part.equals(""))

Page 18: Finding bugs that matter with Findbugs

18

Can you find the Bug?

if (part == null | part.equals(""))

if (part == null || part.equals(""))

Found in //com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser

Page 19: Finding bugs that matter with Findbugs

19

Null Pointer Bugs found in com.sun….

if (name != null || name.length > 0)

if (part == null | part.equals(""))

// sun.awt.x11.ScrollPanePeerif (g != null)

paintScrollBars(g,colors);g.dispose();

Page 20: Finding bugs that matter with Findbugs

20© Availity, LLC | All rights reserved.

//BoundedThreadPool

private final String _lock = "LOCK";...synchronized(_lock){...}

Can you find the Bug?

Page 21: Finding bugs that matter with Findbugs

21© Availity, LLC | All rights reserved.

//BoundedThreadPool private final String _lock = "LOCK";...synchronized(_lock){...}

Constant Strings are shared across all other classes loaded by the JVM. Could lead to unexpected deadlocks in conjunction with other code

found in Jetty….

Page 22: Finding bugs that matter with Findbugs

22

Problem?

public final WritableRaster filter( Raster src, WritableRaster dst) { int dstLength = dst.getNumBands(); // Create a new destination Raster,if needed if (dst == null) dst = createCompatibleDestRaster(src);

Page 23: Finding bugs that matter with Findbugs

23

Redundant Check for Null

public final WritableRaster filter( Raster src, WritableRaster dst) { int dstLength = dst.getNumBands(); // Create a new destination Raster,if needed if (dst == null) dst = createCompatibleDestRaster(src);

can't be null because there would have been a NPE ifit were null

Is it a bug or a redundant check?

Page 24: Finding bugs that matter with Findbugs

24

Can you find the Bug?

if (adapters == null && adapters.length == 0)return;

Eclipse, 3.5RC3

• in Eclipse since 3.2•in this case adapters is probably never null

• Impact:• null pointer exception usually gets noticed• Won’t return if length is 0, error harder to

find

Page 25: Finding bugs that matter with Findbugs

25

Problem?

try { ... }catch (IOException e) { new SAXException("Server side Exception:" + e);}

// com.sun.xml.internal.txw2.output.XMLWriter

Page 26: Finding bugs that matter with Findbugs

26

Bad Method Call

try { ... }catch (IOException e) { new SAXException("Server side Exception:" + e);}

// com.sun.xml.internal.txw2.output.XMLWriter

Exception created and dropped rather than thrown

try { ... }catch (IOException e) { throw new SAXException("Server side Exception:" + e);}

Page 27: Finding bugs that matter with Findbugs

27

Problem?

public static String getNameById(String userId) { String str = userId; ... str.replace(' ', '_');

return str; }

Page 28: Finding bugs that matter with Findbugs

28

Method Ignores return valueCorrectness

public static String getNameById(String userId) { String str = userId; ... str= str.replace(' ', '_');

return str; }

Methods whose return value shouldn't be ignored• Strings are immutable, so functions like trim() and replace() return new String

Page 29: Finding bugs that matter with Findbugs

29

What does it Print?

Integer one = 1;Long addressTypeCode = 1L;

if (addressTypeCode.equals(one)) {System.out.println("equals");

} else {System.out.println("not equals");

}

Page 30: Finding bugs that matter with Findbugs

30

Comparing Different Types

Integer one = 1;Long addressTypeCode = 1L;

if (addressTypeCode.equals(one)) {System.out.println("equals");

} else {System.out.println("not equals");

}

According to the contract of equals(), objects of different classes should always compare as unequal;

Page 31: Finding bugs that matter with Findbugs

31

Incomparable equality

• Using .equals to compare incompatible types• Using .equals to compare arrays

• only checks if the same array

• Checking to see if a Set<Long> contains an Integer • never found, even if the same integral value is contained in the map

• Calling get(String) on a Map<Integer,String>• Returns false , not an error

Silent Bugs hard to find on your own• Types not always explicit• May be introduced by refactoring

• Google refactoring that changed a method to return byte[ ] rather than String

© Availity, LLC | All rights reserved.

Page 32: Finding bugs that matter with Findbugs

32

Best Way to use Findbugs

•Want to find an effective/profitable way to use static analysis to improve software quality

Static Analysis

Deployment

Testing

MistakesThatDon’t

MistakesThatMatter

Page 33: Finding bugs that matter with Findbugs

33

Best Way to use Findbugs

• Find mistakes detected by static analysis before they are detected using more expensive techniques

• While code is fresh in developers heads• Don’t be too eager to fix old issues

Static Analysis

Deployment

Testing

MistakesThatDon’t

MistakesThatMatter

Page 34: Finding bugs that matter with Findbugs

34

Runtime exceptions can be your friend…

Errors which cause a runtime exception are more easily found

Throwing a runtime exception is often a reasonable way to fail safely and report a failure.

runtime exceptions represent conditions that reflect errors in your program's logic and cannot be reasonably recovered from

IllegalArgumentException, NullPointerException, or IllegalStateException

© Availity, LLC | All rights reserved.

Page 35: Finding bugs that matter with Findbugs

35

Expensive Mistakes…

• Mistakes that fail silently • silently cause the wrong answer to be computed

• Mistakes that cause loss of money when they occur• Mistakes that are hard to fix

© Availity, LLC | All rights reserved.

Page 36: Finding bugs that matter with Findbugs

36

Can you find the (Google) bug ?

// calculate DR amount by aggregating CR amountsBigDecimal drAmount = new BigDecimal(0);

for (JournalEntry je: journalEntries) drAmount.add(je.getCrAmount());

// persist to dbgetTrxnService().saveJournalEntry(id,

drAmount, // aggregated amounttrue, // Debit"USD","Revenue");

Page 37: Finding bugs that matter with Findbugs

37

A Google Bug

//Ignored return value of BigDecimal.add

for (JournalEntry je: journalEntries) drAmount.add(je.getCrAmount());

// should be drAmount= drAmount.add(je.getCrAmount());

Fixed within 30 minutes of being reported

Page 38: Finding bugs that matter with Findbugs

38

Bug ?

int value2;Public boolean equals(Integer value1){ return value1== intValue() ;}

public Integer intValue() { return value2;}

Page 39: Finding bugs that matter with Findbugs

39

Using reference equality rather than .equals

int value2;Public boolean equals(Integer value1){ return value1.equals(intValue() );}

public Integer intValue() { return value2;}

For boxed primitives, == and != are computed usingpointer equality, but <, <=, >, >= are computed bycomparing unboxed primitive values

This can bite you on other classes (e.g., String)• but boxed primitives is where people get bit

Page 40: Finding bugs that matter with Findbugs

40

Bug ?

ConcurrentMap<Long,XmitTimeStat> xmit_time_stats = ...;.....stat = new XmitTimeStat();xmit_time_stats.putIfAbsent(key, stat);stat.xmit_rsps_sent.addAndGet(sent);

Page 41: Finding bugs that matter with Findbugs

41

misusing putIfAbsentorg.jgroups.protocols.pbcast.NAKACK

ConcurrentMap<Long,XmitTimeStat> xmit_time_stats = ...;.....stat = new XmitTimeStat();XmitTimeStat stat2 = xmit_time_stats.putIfAbsent(key, stat);if (stat2 != null) stat = stat2;stat.xmit_rsps_sent.addAndGet(sent);

ConcurrentMap provides putIfAbsent• atomically add key → value mapping• but only if the key isnʼt already in the map• if non-null value is returned, put failed and valuereturned is the value already associated with the key

Page 42: Finding bugs that matter with Findbugs

42

Concurrency Bugs

• Lots of concurrency bugs are found• They don’t cause as many problems as they should• Problems will probably increase with bigger core

systems• Early reports from 768 core systems are that they

have more severe problems

© Availity, LLC | All rights reserved.

Page 43: Finding bugs that matter with Findbugs

43

Concurrency Bugs

• Inconsistent synchronization – • a lock is held sometimes when field accessed

• Problems with wait/notify – • e.g., call to wait() not in loop

• unsafe lazy initialization of static field

© Availity, LLC | All rights reserved.

Page 44: Finding bugs that matter with Findbugs

44

Bug ?

synchronized (object) {  if (<condition does not hold>) {    object.wait();  }  // Proceed when condition holds}

Page 45: Finding bugs that matter with Findbugs

45

call to wait() not in loop

synchronized (object) {  while (<condition does not hold>) {    object.wait();  }  // Proceed when condition holds}

Page 46: Finding bugs that matter with Findbugs

46

Concurrency Bugs

• Java 5 simplified concurrency • In Joshua Blochʼs said: don’t lock on

ConcurrentMaps

• Bill Pugh wrote a detector for FindBugs

© Availity, LLC | All rights reserved.

Page 47: Finding bugs that matter with Findbugs

47

JBoss 5.1.0-GA

• 22 synchonizations on ConcurrentHashMap• 9 synchronizations on CopyOnWriteArrayList• 3 synchronizations on AtomicBoolean

© Availity, LLC | All rights reserved.

Page 48: Finding bugs that matter with Findbugs

48

Security Bugs

• Not exposed by normal test use cases• Need:

• Risk analysis, careful design, static analysis, dynamic testing and analysis

• Findbugs does simple analysis for network security vulnerabilities

© Availity, LLC | All rights reserved.

Page 49: Finding bugs that matter with Findbugs

49

Some security Bugs

• Vulnerability to untrusted, malicious code:• public static non-final fields• Methods that don’t defensively copy mutable arguments before

storing them into fields• Methods that don’t defensively copy mutable values stored in fields

before returning them

• Untrusted input:• Included in SQL• included in HTTP response• Forming a file path

© Availity, LLC | All rights reserved.

Page 50: Finding bugs that matter with Findbugs

50

Running FindBugs

• Eclipse plugin• http://findbugs.sourceforge.net/manual/eclipse.html

• Run with Hudson build

© Availity, LLC | All rights reserved.

Page 51: Finding bugs that matter with Findbugs

51

Findbugs plugin in Eclipse

Page 52: Finding bugs that matter with Findbugs

52

References

• Findbugs home page• http://findbugs.sourceforge.net/

• Bill Pugh Findbugs Devoxx talk• http://www.parleys.com/#id=2106&st=5

• Bill Pugh Oredev talk:• http://oredev.org/2010/sessions/defective-java-mistakes-that-matter

© Availity, LLC | All rights reserved.