1 / 53

Detecting non-local violations of API contracts in large software systems

Eric Bodden McGill University. Detecting non-local violations of API contracts in large software systems. public class Logging { private static Writer w ; public static void init( OutputStream os ) { w = new PrintWriter ( os ); } public static void log(String s ) {

espen
Download Presentation

Detecting non-local violations of API contracts in large software systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Eric Bodden McGill University Detecting non-localviolations of API contracts inlarge software systems

  2. public class Logging { private static Writer w; public staticvoid init(OutputStreamos) { w = new PrintWriter(os); } public static void log(String s) { w.write(s); } public static voidlogAll(Reader r) { StreamUtil.copyAll(r,w); } }

  3. One month later…

  4. “Feature X is not working”

  5. “Could you have a look at the log file, please?”

  6. “The log file is empty!”

  7. “Customer says, the log is empty…” • “Oh no! • How come?”

  8. public class Logging { private static Writer w; public staticvoid init(OutputStreamos) { w = new PrintWriter(os); } public static void log(String s) { w.write(s); } public static voidlogAll(Reader r) { StreamUtil.copyAll(r,w); } }

  9. static voidcopyAll(Reader r, Writer w) { intbuffer = 0; try { do { buffer = r.read(); w.write(buffer); } while(buffer!=-1); } finally { r.close(); w.close(); } }

  10. One hour later…

  11. public class Logging { private static Writer w; public staticvoid init(OutputStreamos) { w = new PrintWriter(os); } public static void log(String s) { w.write(s); } public static voidlogAll(Reader r) { StreamUtil.copyAll(r,w); } }

  12. A better world…

  13. Possible API violation on Writer w public class Logging { private static Writer w; public staticvoid init(OutputStreamos) { w = new PrintWriter(os); } public static void log(String s) { w.write(s); } public static voidlogAll(Reader r) { StreamUtil.copyAll(r,w); } } I’m feeling lucky Show API contract Ignore

  14. API violation on Writer w public class Logging { private static Writer w; public staticvoid init(OutputStreamos) { w = new PrintWriter(os); } public static void log(String s) { w.write(s); } public static voidlogAll(Reader r) { StreamUtil.copyAll(r,w); } } • StreamUtil.copyAll(..) Show API contract Ignore

  15. Detecting non-local violationsof API contracts inlarge software systems

  16. Non-local violations • involve aliasing through long call chains

  17. API contracts: • Client contracts that come along with an API.

  18. Large software systems: • Complete Java programs with up to hundreds of thousands lines of code

  19. Pure runtime monitoring • How does it work today?

  20. “no writeafter close” abc compiler

  21. How to specifyAPI contracts?

  22. Current approach: Tracematches tracematch(Writer w) { sym close after returning: call(* Writer.close()) && target(w);sym write before: call(* Writer.write(..)) && target(w); close write { System.out.println( “Writer ”+w+“ was closed!”); } }

  23. close write true w = o(w1) false false w = o(w1) w1.close(); w1.write(“foo”); w1.write(“foo”); • { • System.out.println( “Writer ”+w+“ was closed!”); • }

  24. Problem 1: • Potentially largeruntime overhead

  25. Problem 2: • No static guarantees

  26. “no writeafter close” 4 novel staticprogram analyses

  27. First static analysis: • “Quick • Check”

  28. close write count( ) = 0 count( ) = 2

  29. Second static analysis: “Consistent-shadows analysis”

  30. close write [close,write]

  31. [close,write] w1 w2 c1 {c1} {w1,w2} x new PrintWriter(); {c1, w1} o2 o1 • {c1, w2}

  32. Third static analysis: “Flow-sensitive unnecessary shadows analysis”

  33. close write w = i(w1)-s1 true false false w = i(w1)-s1,s2 w ≠ i(w1)-s2 true true false w = i(w1)-s1,s2 V w =i(w1)-s1 w1.close(); w1.write(“foo”); w1.write(“foo”); //s1 //s2 //s3

  34. 4th static analysis: “run-once loop optimization”

  35. 1 2 3 4 5

  36. 1 1 1 1

  37. 1

  38. Results • |.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|. • |.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|. • |.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|. • |.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|. • 102 program/tracematch combinations • static guarantees in 77 cases • Found 5 programs (out of 12 ) with bugs or questionable code. • less than 10 shadows in 12 cases • less than 10% overhead in 9 cases

  39. Jython / Reader (1/2) private final void FillBuff() { ... try { if ((i = inputStream.read(...)) == -1) { inputStream.close(); throw new java.io.IOException(); } else maxNextCharInd += i; return; } ... }

  40. Jython / Reader (2/2) static String getLine(BufferedReader reader, int line) { if (reader == null) return ""; try { String text=null; for(inti=0; i < line; i++) { text = reader.readLine(); } return text; } catch (IOExceptionioe) { return null; } }

  41. Jython / hasNext (delegate) public Iterator iterator() { return new Iterator() { Iterator i = list.iterator(); public void remove() { throw new UnsupportedOperationException(); } public booleanhasNext() { return i.hasNext(); } public Object next() { return i.next(); } }; }

More Related