Successfully reported this slideshow.
Your SlideShare is downloading. ×

Hidden Truths in Dead Software Paths

Loading in …3
×

Check these out next

1 of 18
1 of 18

Hidden Truths in Dead Software Paths

Download to read offline

Approaches and techniques for statically finding a multitude of issues in source code have been developed in the past. A core property of these approaches is that they are usually targeted towards finding only a very specific kind of issue and that the effort to develop such an analysis is significant. This strictly limits the number of kinds of issues that can be detected.
In this paper, we discuss a generic approach based on the detection of infeasible paths in code that can discover a wide range of code smells ranging from useless code that hinders comprehension to real bugs. Code issues are identified by calculating the difference between the control-flow graph that contains all technically possible edges and the corresponding graph recorded while performing a more precise analysis using abstract interpretation.
We have evaluated the approach using the Java Development Kit as well as the Qualitas Corpus (a curated collection of over 100 Java Applications) and were able to find thousands of issues across a wide range of categories.

Approaches and techniques for statically finding a multitude of issues in source code have been developed in the past. A core property of these approaches is that they are usually targeted towards finding only a very specific kind of issue and that the effort to develop such an analysis is significant. This strictly limits the number of kinds of issues that can be detected.
In this paper, we discuss a generic approach based on the detection of infeasible paths in code that can discover a wide range of code smells ranging from useless code that hinders comprehension to real bugs. Code issues are identified by calculating the difference between the control-flow graph that contains all technically possible edges and the corresponding graph recorded while performing a more precise analysis using abstract interpretation.
We have evaluated the approach using the Java Development Kit as well as the Qualitas Corpus (a curated collection of over 100 Java Applications) and were able to find thousands of issues across a wide range of categories.

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Hidden Truths in Dead Software Paths

  1. 1. Hidden Truths in Dead Software Paths Michael Eichberg, Ben Hermann, Mira Mezini, and Leonid Glanz ESEC/FSE 2015, Bergamo, Italy
  2. 2. When is a path dead? if  (maxBits  >  4  ||  maxBits  <  8)  {        maxBits  =  8;   }   if  (maxBits  >  8)  {        maxBits  =  16;   } OpenJDK 8 update 25, com.sun.imageio.plugins.png.PNGMetadata, line 1842ff Hidden inside a 278 LOC method
  3. 3. Hypothesis In well-written code every path between an instruction and all its successors is eventually taken A path that will never be taken indicates an issue
  4. 4. Identifying Infeasible Paths public  static  X  doX(SomeType[]  array)  {   if  (array  !=  null  ||  array.length  >  0)  {  (a)  }   //  …  (b)   }//  (ex) 1: public static X doX(SomeType[] array){ 2: if (array != null || array.length > 0) {(a) } 5: // … (b) 6: }// (ex) ifnonnull array arraylength array ifgt (>0) (a) (b) (ex) (B) Corresponding CFG true true false false (A) Java Source Code. ifnonnull array arraylength array ifgt (>0) (C) Computed AIFG false Java Bytecode Java Bytecode :- array is null CFG
  5. 5. Identifying Infeasible Paths 1: public static X doX(SomeType[] array){ 2: if (array != null || array.length > 0) {(a) } 5: // … (b) 6: }// (ex) ifnonnull array arraylength array ifgt (>0) (a) (b) (ex) (B) Corresponding CFG true true false false ifnonnull array arraylength array ifgt (>0) (a) (b) (ex) (C) Computed AIFG true true false false relevant missing edge a missing edge Java Bytecode Java Bytecode :- array is null :- array not null 1: public static X doX(SomeType[] array){ 2: if (array != null || array.length > 0) {(a) } 5: // … (b) 6: }// (ex) ifnonnull array arraylength array ifgt (>0) (a) (b) (ex) (B) Corresponding CFG true true false false ifnonnull array arraylength array ifgt (>0) (a) (b) (ex) (C) Computed AIFG true true false false relevant missing edge a missing edge Java Bytecode Java Bytecode :- array is null :- array not null CFG AIFG
  6. 6. Abstract Interpretation Not targeted at a specific goal Not a whole program analysis, but instead everything may be an entry point Inter-procedural, path-, flow-, object- and context-sensitive
 with configurable call chain length (typically low)
  7. 7. Abstract Interpretation Integers support all arithmetic operations (of the JVM) maximum size for intervals before we consider them as AnyInt float, long, double at type level reference values objects distinguished by their allocation site alias- and path-sensitive
  8. 8. Post-Processing Compiler Generated Dead Code The Intricacies of Java Established Idioms Assertions Reflection and Reflection-like Mechanisms
  9. 9. Post-Processing Compiler Generated Dead Code void  conditionInFinally(java.io.File  f)  {   boolean  completed  =  false;   try  {   f.canExecute();   completed  =  true;   }  finally  {     if  (completed)  doSomething();  }   } Finally blocks are included twice by Java compilers
  10. 10. Post-Processing The Intricacies of Java Throwable  doFail()  {  throw  new  Exception();  }   Object  compute(Object  o)  {   if  (o  ==  null)  {  return  doFail();  }   else  return  o;   }
  11. 11. Post-Processing Established Idioms switch  (i)  {   case  1:  break;   //  complete  enumerable  of  all  cases   default:  throw  new  UnknownError();   }
  12. 12. Post-Processing Assertions Reflection and Reflection-like Mechanisms
  13. 13. Study: JDK 8 Update 25 Category Percentage Null Confusion 54 % Range Double Checks 11 % Dead Extensibility 9 % Unsupported Operation Usage 7 % Unexpected Return Value 5 % Forgotten Constant 4 % Confused Language Semantics 3 % Type Confusion 3 % Confused Conjunctions 2 % Obviously Useless Code 1 % False Positives 1 % • Found 556 issues • For 19 we found no source code • 279 of 537 were considered irrelevant • The remaining 258 issues were manually inspected
  14. 14. Null Confusion Infeasible path because of too much checks for null Infeasible path because of too less checks for null if  (o  ==  null)  return  doSomething();   if  (o  ==  null)  return  doSomeOtherThing(); int  num  =  array.length;   if  (array  ==  null)     throw  InvalidArgumentException();
  15. 15. Range Double Checks if  (extendableSpaces  <=  0)  return;   int  adjustment  =  (target  -­‐  currentSpan);   int  spaceAddon  =  (extendableSpaces  >  0)  ?   adjustment  /  extendableSpaces  :  0; OpenJDK 8 update 25, javax.swing.text.ParagraphView$Row.layoutMajorAxis, line 1095ff
  16. 16. Dead Extensibility //  For  now  we  set  owner  to  null.  In  the   future,  it  may  be  
 //  passed  as  an  argument.  
 Window  owner  =  null;  
 if  (owner  instanceof  Frame)  {  ...  } OpenJDK 8 update 25, javax.print.ServiceUI.printDialog, line 189ff
  17. 17. Summary General analysis approach to find various different and complex issues Dead Path detection using Abstract Interpretation We evaluated on the JDK (and on the Qualitas Corpus) We filter out irrelevant issues
  18. 18. Thanks and please try it out http://www.opal-­‐project.de/tools/bugpicker/ And also see my other talk on a Capability Model for Java on Friday’s 11:30 session R8.c in the same room

×