detecting non-local violations of api contracts in large software systems

53
Detecting non-local violations of API contracts in large software systems Eric Bodden McGill University

Upload: espen

Post on 25-Feb-2016

34 views

Category:

Documents


0 download

DESCRIPTION

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 ) { - PowerPoint PPT Presentation

TRANSCRIPT

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

Detecting non-localviolations of API

contracts inlarge software

systems

Eric Bodden McGill University

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

2

public class Logging {

private static Writer w;

public static void init(OutputStream os) {w = new PrintWriter(os);

}

public static void log(String s) {w.write(s);

}

public static void logAll(Reader r) {StreamUtil.copyAll(r,w);

}

}

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

One month later…

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

“Feature X is not

working”

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

“Could you have a look at

the log file, please?”

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

“The log file is empty!”

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

“Customer says, the log is

empty…”

“Oh no! How come?”

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

8

public class Logging {

private static Writer w;

public static void init(OutputStream os) {w = new PrintWriter(os);

}

public static void log(String s) {w.write(s);

}

public static void logAll(Reader r) {StreamUtil.copyAll(r,w);

}

}

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

static void copyAll(Reader r, Writer w) {

int buffer = 0;try {

do {buffer = r.read();w.write(buffer);

} while(buffer!=-1);} finally {

r.close();w.close();

}}

9

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

One hour later…

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

11

public class Logging {

private static Writer w;

public static void init(OutputStream os) {w = new PrintWriter(os);

}

public static void log(String s) {w.write(s);

}

public static void logAll(Reader r) {StreamUtil.copyAll(r,w);

}

}

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

12

Page 13: Detecting non-local violations of API contracts in large software systems
Page 14: Detecting non-local violations of API contracts in large software systems
Page 15: Detecting non-local violations of API contracts in large software systems

A better world…

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

16

public class Logging {

private static Writer w;

public static void init(OutputStream os) {w = new PrintWriter(os);

}

public static void log(String s) {w.write(s);

}

public static void logAll(Reader r) {StreamUtil.copyAll(r,w);

}

}

Possible API violation on Writer w

I’m feeling lucky Show API contract Ignore

w implements type Writer, whose contract is violated.At this line, w may be in state closed. – Why?The operation write(String) is not allowed in that state.Avoid the violation by making sure that w is not the closed state. - How?

Page 17: Detecting non-local violations of API contracts in large software systems
Page 18: Detecting non-local violations of API contracts in large software systems

18

public class Logging {

private static Writer w;

public static void init(OutputStream os) {w = new PrintWriter(os);

}

public static void log(String s) {w.write(s);

}

public static void logAll(Reader r) {StreamUtil.copyAll(r,w);

}

}

API violation on Writer w

StreamUtil.copyAll(..) Show API contract Ignore

w implements type Writer, whose contract is violated.w is currently in state closed, caused by StreamUtil.copyAll(..)The operation write(String) is not allowed in that state.

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

Detecting non-local violations

of API contracts inlarge software

systems

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

Non-local violations

involve aliasing

through long call chains

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

21

API contracts:Client contracts that come along

with an API.

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

22

Large software systems:

Complete Java programs with up

to hundreds of thousands lines of

code

Page 23: Detecting non-local violations of API contracts in large software systems
Page 24: Detecting non-local violations of API contracts in large software systems

Pure runtime

monitoring

How does it work today?

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

25

abc compiler

“no writeafter close”

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

How to specifyAPI contracts?

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

27

Current approach: Tracematchestracematch(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!”);

}}

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

close write

w1.close();

w1.write(“foo”);

w1.write(“foo”);

true falsew = o(w1) falsew = o(w1)

{System.out.println(

“Writer ”+w+“ was closed!”);

}

28

Page 29: Detecting non-local violations of API contracts in large software systems
Page 30: Detecting non-local violations of API contracts in large software systems

Problem 1:

Potentially large

runtime overhead

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

Problem 2:No static

guarantees

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

32

“no writeafter close”

4 novel staticprogram analyses

Page 33: Detecting non-local violations of API contracts in large software systems
Page 34: Detecting non-local violations of API contracts in large software systems

First static

analysis:

“QuickCheck”

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

38

count( ) = 2

count( ) = 0

close write

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

Second static

analysis:

“Consistent-

shadows analysis”

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

close write

[close,write]

40

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

o1 o2

{c1} {w1,w2}x

{c1, w1}

{c1, w2}41

new PrintWriter();

w1w2c1

[close,write]

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

Third static analysis:

“Flow-sensitive

unnecessary shadows analysis”

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

43

w1.close();

w1.write(“foo”);

w1.write(“foo”);

//s1

//s2

//s3

true false false

w =i(w1)-s1true true false

w = i(w1)-s1w ≠ i(w1)-s2V

w = i(w1)-s1,s2w = i(w1)-s1,s2

close write

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

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

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

1

2

3

4

5

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

1 1

1 1

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

47

1

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

48

|.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|.

|.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|.

|.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|.

Results

102 program/tracematch combinationsstatic guarantees in 77 cases

less than 10 shadows in 12 casesless than 10% overhead in 9 cases

|.........|.........|.........|.........|.........|.........|.........|.........|.........|.........|.

Found 5 programs (out of 12 ) with bugs or questionable

code.

Page 46: Detecting non-local violations of API contracts in large software systems
Page 47: Detecting non-local violations of API contracts in large software systems
Page 48: Detecting non-local violations of API contracts in large software systems

private final void FillBuff() {...try {

if ((i = inputStream.read(...)) == -1) {inputStream.close();throw new java.io.IOException();

}else

maxNextCharInd += i;return;

}...

}

Jython / Reader (1/2)

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

52

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

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

53

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

} public Object next() { return i.next();

} };}

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

54

pmd / HasNext (old version)private List markUsages(IDataFlowNode inode) {

...for (Iterator k = ((List)entry.getValue())

.iterator();k.hasNext();) {addAccess(k, inode);

}...

}

...

private void addAccess(Iterator k, IDataFlowNode inode) {

NameOccurrence occurrence =(NameOccurrence) k.next();

... }

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

55

pmd / HasNext (fixed version)private List markUsages(IDataFlowNode inode) {

... for (NameOccurrence occurrence: entry.getValue())

{addAccess(occurrence, inode);

}...

}

...

private void addAccess(NameOccurrence occurrence,IDataFlowNode inode) {

... }

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

56

pmd / HasNext (isEmpty())protected NameDeclaration

findVariableHere(NameOccurrence occurrence) {if (occurrence.isThisOrSuper() || occurrence.getImage().equals(className)) {

if (variableNames.isEmpty() &&methodNames.isEmpty()) {return null;

}if (!variableNames.isEmpty()) {

return variableNames.keySet().iterator().next();

}return methodNames.keySet().

iterator().next();}...

}