Skip to content

Commit

Permalink
feat(spgroup#31): add stacktrace
Browse files Browse the repository at this point in the history
  • Loading branch information
barbosamaatheus committed Sep 22, 2021
1 parent 1580c0f commit 97c4131
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import br.unb.cic.analysis.df.DataFlowAbstraction;
import br.unb.cic.analysis.model.Conflict;
import br.unb.cic.analysis.model.Statement;
import br.unb.cic.analysis.model.TraversedLine;
import br.unb.cic.exceptions.ValueNotHandledException;
import soot.*;
import soot.jimple.*;
Expand All @@ -28,6 +29,7 @@ public class InterproceduralOverrideAssignment extends SceneTransformer implemen
private final AbstractMergeConflictDefinition definition;
private final FlowSet<DataFlowAbstraction> left;
private final FlowSet<DataFlowAbstraction> right;
private List<TraversedLine> stacktraceList;

private final Logger logger;

Expand All @@ -39,6 +41,7 @@ public InterproceduralOverrideAssignment(AbstractMergeConflictDefinition definit
this.right = new ArraySparseSet<>();
this.traversedMethods = new ArrayList<>();
this.pointsToAnalysis = Scene.v().getPointsToAnalysis();
this.stacktraceList = new ArrayList<>();

this.logger = Logger.getLogger(
InterproceduralOverrideAssignment.class.getName());
Expand Down Expand Up @@ -95,7 +98,8 @@ protected void internalTransform(String s, Map<String, String> map) {
* The remaining statements of the current method that have no markup will be marked according to the flowChangeTag.
* @return the result of applying the analysis considering the income abstraction (in) and the sootMethod
*/
private FlowSet<DataFlowAbstraction> traverse(FlowSet<DataFlowAbstraction> in, SootMethod sootMethod, Statement.Type flowChangeTag) {
private FlowSet<DataFlowAbstraction> traverse(FlowSet<DataFlowAbstraction> in, SootMethod sootMethod,
Statement.Type flowChangeTag) {
//System.out.println(sootMethod);
if (this.traversedMethods.contains(sootMethod) || sootMethod.isPhantom()) {
return in;
Expand All @@ -107,11 +111,16 @@ private FlowSet<DataFlowAbstraction> traverse(FlowSet<DataFlowAbstraction> in, S

if (body != null) {
for (Unit unit : body.getUnits()) {
TraversedLine traversedLine = new TraversedLine(sootMethod, unit.getJavaSourceStartLineNumber());

if (isTagged(flowChangeTag, unit)) {
addStackTrace(traversedLine);
in = runAnalysisWithTaggedUnit(in, sootMethod, flowChangeTag, unit);
} else {
in = runAnalysisWithBaseUnit(in, sootMethod, flowChangeTag, unit);
}

removeStackTrace(traversedLine);
}
}

Expand Down Expand Up @@ -160,16 +169,16 @@ private FlowSet<DataFlowAbstraction> runAnalysis(FlowSet<DataFlowAbstraction> in
AssignStmt assignStmt = (AssignStmt) unit;

if (assignStmt.containsInvokeExpr()) {
return executeCallGraph(in, flowChangeTag, unit);
return executeCallGraph(in, flowChangeTag, unit, sootMethod);
}

separeteAbstraction(in);
if (tagged) {
Statement stmt = getStatementAssociatedWithUnit(sootMethod, unit, flowChangeTag);
setStackTraceInStmt(stmt);
// logger.log(Level.INFO, () -> String.format("%s", "stmt: " + stmt.toString()));
separeteAbstraction(in);
gen(in, stmt);
} else {
separeteAbstraction(in);
kill(in, unit);
}

Expand All @@ -191,7 +200,7 @@ In this case, this condition will be executed for the call to the foo() method a
For builders, InvokeExpression is an instance of InvokeSpecial */

} else if (unit instanceof InvokeStmt) {
return executeCallGraph(in, flowChangeTag, unit);
return executeCallGraph(in, flowChangeTag, unit, sootMethod);
}

return in;
Expand All @@ -210,7 +219,8 @@ private void separeteAbstraction(FlowSet<DataFlowAbstraction> in) {
});
}

private FlowSet<DataFlowAbstraction> executeCallGraph(FlowSet<DataFlowAbstraction> in, Statement.Type flowChangeTag, Unit unit) {
private FlowSet<DataFlowAbstraction> executeCallGraph(FlowSet<DataFlowAbstraction> in,
Statement.Type flowChangeTag, Unit unit, SootMethod sootMethod) {
CallGraph callGraph = Scene.v().getCallGraph();
Iterator<Edge> edges = callGraph.edgesOutOf(unit);

Expand All @@ -219,11 +229,11 @@ private FlowSet<DataFlowAbstraction> executeCallGraph(FlowSet<DataFlowAbstractio
while (edges.hasNext()) {
Edge e = edges.next();
SootMethod method = e.getTgt().method();

Statement stmt = getStatementAssociatedWithUnit(method, unit, flowChangeTag);

FlowSet<DataFlowAbstraction> traverseResult = traverse(in.clone(), method, stmt.getType());
flowSetList.add(traverseResult);

}

FlowSet<DataFlowAbstraction> flowSetUnion = new ArraySparseSet<>();
Expand Down Expand Up @@ -259,9 +269,6 @@ private void gen(FlowSet<DataFlowAbstraction> in, Statement stmt) {

} else if (isLefAndRightStatement(stmt)) {
addConflict(stmt, stmt);

//addStmtToList(stmt, left);

}
addStmtToList(stmt, in);
}
Expand Down Expand Up @@ -359,6 +366,18 @@ private Statement getStatementAssociatedWithUnit(SootMethod sootMethod, Unit u,
return createStatement(sootMethod, u, Statement.Type.IN_BETWEEN);
}

private void setStackTraceInStmt(Statement stmt) {
stmt.setStacktrace(new ArrayList<TraversedLine>(this.stacktraceList));
}

private void addStackTrace(TraversedLine traversedLine) {
this.stacktraceList.add(traversedLine);
}

private void removeStackTrace(TraversedLine traversedLine) {
this.stacktraceList.remove(traversedLine);
}

private boolean isBothUnitOrBothStatementFlow(Unit u, Statement.Type flowChangeTag) {
if (isRightUnit(u) && isInLeftStatementFlow(flowChangeTag)) {
return true;
Expand Down
23 changes: 20 additions & 3 deletions src/main/java/br/unb/cic/analysis/model/Conflict.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import soot.Unit;

import java.util.List;
import java.util.Objects;

/**
Expand All @@ -13,21 +14,26 @@ public class Conflict {
protected String sourceClassName;
protected String sourceMethodName;
protected Integer sourceLineNumber;
protected Unit sourceUnit;
protected List<TraversedLine> sourceTraversedLine;
protected String sinkClassName;
protected String sinkMethodName;
protected Integer sinkLineNumber;
protected Unit sourceUnit;
protected Unit sinkUnit;
protected List<TraversedLine> sinkTraversedLine;


public Conflict(Statement source, Statement sink) {
this.sourceClassName = source.getSootClass().getName();
this.sourceMethodName = source.getSootMethod().getName();
this.sourceLineNumber = source.getSourceCodeLineNumber();
this.sourceUnit = source.getUnit();
this.sourceTraversedLine = source.getStacktrace();
this.sinkClassName = sink.getSootClass().getName();
this.sinkMethodName = sink.getSootMethod().getName();
this.sinkLineNumber = sink.getSourceCodeLineNumber();
this.sinkUnit = sink.getUnit();
this.sinkTraversedLine = sink.getStacktrace();
}

@Deprecated
Expand All @@ -40,6 +46,7 @@ public Conflict(String sourceClassName, String sourceMethodName, Integer sourceL
this.sinkLineNumber = sinkLineNumber;
}


public String getSourceClassName() {
return sourceClassName;
}
Expand Down Expand Up @@ -84,9 +91,19 @@ public int hashCode() {
return Objects.hash(sourceClassName, sourceMethodName, sourceLineNumber, sinkClassName, sinkMethodName, sinkLineNumber);
}

/* @Override
public String toString() {
return String.format("source(%s, %s, %d, %s, %s) => sink(%s, %s, %d, %s, %s)", sourceTraversedLine.get(0).getSootClass(),
sourceTraversedLine.get(0).getSootMethod(), sourceTraversedLine.get(0).getLineNumber(), sourceUnit,
sourceTraversedLine,
sinkTraversedLine.get(0).getSootClass(), sinkTraversedLine.get(0).getSootMethod(),
sinkTraversedLine.get(0).getLineNumber(), sinkUnit, sinkTraversedLine);
}*/

@Override
public String toString() {
return String.format("source(%s, %s, %d, %s) => sink(%s, %s, %d, %s)", sourceClassName, sourceMethodName, sourceLineNumber, sourceUnit,
sinkClassName, sinkMethodName, sinkLineNumber, sinkUnit);
return String.format("source(%s, %s, %d, %s, %s) => sink(%s, %s, %d, %s, %s)", sourceClassName,
sourceMethodName, sourceLineNumber, sourceUnit, sourceTraversedLine,
sinkClassName, sinkMethodName, sinkLineNumber, sinkUnit, sinkTraversedLine);
}
}
58 changes: 35 additions & 23 deletions src/main/java/br/unb/cic/analysis/model/Statement.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import soot.SootMethod;
import soot.Unit;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
Expand All @@ -24,32 +26,42 @@ public enum Type {

public static StatementBuilder builder() {
if(builder == null) {
builder = new StatementBuilder();
}
return builder;
}
builder = new StatementBuilder();
}
return builder;
}

private SootClass sootClass;
private SootMethod sootMethod;
private Unit unit;
private Type type;
private Integer sourceCodeLineNumber;

Statement(SootClass sootClass, SootMethod sootMethod, Unit unit, Type type, Integer sourceCodeLineNumber) {
this.sootClass = sootClass;
this.sootMethod = sootMethod;
this.unit = unit;
this.type = type;
this.sourceCodeLineNumber = sourceCodeLineNumber;
}
private SootClass sootClass;
private SootMethod sootMethod;
private Unit unit;
private Type type;
private Integer sourceCodeLineNumber;
private List<TraversedLine> traversedLine;

public SootClass getSootClass() {
return sootClass;
}
Statement(SootClass sootClass, SootMethod sootMethod, Unit unit, Type type, Integer sourceCodeLineNumber) {
this.sootClass = sootClass;
this.sootMethod = sootMethod;
this.unit = unit;
this.type = type;
this.sourceCodeLineNumber = sourceCodeLineNumber;
this.traversedLine = new ArrayList<>();
}

public SootMethod getSootMethod() {
return sootMethod;
}
public List<TraversedLine> getStacktrace() {
return traversedLine;
}

public void setStacktrace(List<TraversedLine> traversedLine) {
this.traversedLine = traversedLine;
}

public SootClass getSootClass() {
return sootClass;
}

public SootMethod getSootMethod() {
return sootMethod;
}

public Unit getUnit() {
return unit;
Expand Down
55 changes: 55 additions & 0 deletions src/main/java/br/unb/cic/analysis/model/TraversedLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package br.unb.cic.analysis.model;

import soot.SootClass;
import soot.SootMethod;

public class TraversedLine {
protected SootClass sootClass;
protected SootMethod sootMethod;
protected Integer lineNumber;

public TraversedLine(SootClass sootClass, SootMethod sootMethod, Integer lineNumber) {
this.sootClass = sootClass;
this.sootMethod = sootMethod;
this.lineNumber = lineNumber;
}

public TraversedLine(SootMethod sootMethod, Integer lineNumber) {
this.sootClass = sootMethod.getDeclaringClass();
this.sootMethod = sootMethod;
this.lineNumber = lineNumber;
}

public SootClass getSootClass() {
return sootClass;
}

public void setSootClass(SootClass sootClass) {
this.sootClass = sootClass;
}

public SootMethod getSootMethod() {
return sootMethod;
}

public void setSootMethod(SootMethod sootMethod) {
this.sootMethod = sootMethod;
}

public Integer getLineNumber() {
return lineNumber;
}

public void setLineNumber(Integer lineNumber) {
this.lineNumber = lineNumber;
}

@Override
public String toString() {
return "Stacktrace{" +
"sootClass=" + sootClass.getShortJavaStyleName() +
", sootMethod=" + sootMethod.getSubSignature() +
", lineNumber=" + lineNumber +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ private void configureSootOptions(List<String> testClasses) {
Options.v().set_include(getIncludeList());
}


@Test
public void stacktraceConflictSample() {
String sampleClassPath = "br.unb.cic.analysis.samples.ioa.StacktraceConflictSample";
AbstractMergeConflictDefinition definition = DefinitionFactory
.definition(sampleClassPath, new int[]{12}, new int[]{13});
InterproceduralOverrideAssignment analysis = new InterproceduralOverrideAssignment(definition);
configureTest(analysis);
Assert.assertEquals(2, analysis.getConflicts().size());
}

@Test
public void subclassWithConditionalTeste() {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package br.unb.cic.analysis.samples.ioa;

// Conflict: [left, m():11] --> [right, m():12]
public class StacktraceConflictSample {
private int x, y;

public void main() {
StacktraceConflictSample m = new StacktraceConflictSample();

m.foo(); // LEFT
m.bar(); // RIGHT
}

private void foo() {
qux();
System.out.println();
y = 1;
}

private void bar() {
x = 2;
y = 2;
}

private void qux() {
x = 3;
System.out.println();
}
}

0 comments on commit 97c4131

Please sign in to comment.