Skip to content

Commit

Permalink
Merge pull request #39 from galilasmb/develop
Browse files Browse the repository at this point in the history
Resolving old merge conflicts
  • Loading branch information
pauloborba authored Apr 5, 2021
2 parents 3aae192 + 6be6d5e commit 49bc5fa
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 58 deletions.
38 changes: 26 additions & 12 deletions src/main/java/br/unb/cic/analysis/df/DataFlowAbstraction.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import soot.Local;
import soot.Value;
import soot.jimple.InstanceFieldRef;
import soot.jimple.InvokeStmt;
import soot.jimple.StaticFieldRef;

import java.util.Objects;
import java.util.*;

/**
* Information wee keep while traversing
Expand All @@ -17,8 +18,14 @@ public class DataFlowAbstraction {
private Local local;
private InstanceFieldRef localField;
private StaticFieldRef localStaticRef;
private Value value;
private InvokeStmt methodCall;
private Statement stmt;
private Value value;

public DataFlowAbstraction(InvokeStmt methodCall, Statement stmt){
this.methodCall = methodCall;
this.stmt = stmt;
}

public DataFlowAbstraction(Value value, Statement stmt) {
this.value = value;
Expand All @@ -40,6 +47,14 @@ public DataFlowAbstraction(StaticFieldRef localStaticRef, Statement stmt) {
this.stmt = stmt;
}

public InvokeStmt getMethodCall() {
return methodCall;
}

public void setMethodCall(InvokeStmt methodCall) {
this.methodCall = methodCall;
}

public Local getLocal() {
return local;
}
Expand All @@ -48,16 +63,23 @@ public StaticFieldRef getLocalStaticRef() {
return localStaticRef;
}

public Value getValue() {
return value;
}

public void setValue(Value value) {
this.value = value;
}

public InstanceFieldRef getFieldRef() {
return localField;
}

public Statement getStmt() {
return stmt;
}

public Boolean containsLeftStatement(){
return getStmt().getType().equals(Statement.Type.SOURCE);
return getStmt().getType().equals(Statement.Type.SOURCE);
}

public Boolean containsRightStatement(){
Expand All @@ -77,12 +99,4 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(local, stmt);
}

public Value getValue() {
return this.value;
}

public void setValue(Value value) {
this.value = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
import br.unb.cic.analysis.model.Conflict;
import br.unb.cic.analysis.model.Statement;
import soot.*;
import soot.jimple.ArrayRef;
import soot.jimple.InstanceFieldRef;
import soot.jimple.StaticFieldRef;
import soot.jimple.*;
import soot.toolkits.scalar.ArraySparseSet;
import soot.toolkits.scalar.FlowSet;

Expand Down Expand Up @@ -78,14 +76,17 @@ protected FlowSet<DataFlowAbstraction> gen(Unit u, FlowSet<DataFlowAbstraction>

if (isLeftStatement(u) || isRightStatement(u)) {
Statement stmt = getStatementAssociatedWithUnit(u);
if (u instanceof InvokeStmt){
res.add(new DataFlowAbstraction((InvokeStmt) u, stmt));
}
u.getDefBoxes().forEach(valueBox -> {
if (valueBox.getValue() instanceof Local) {
if (valueBox.getValue() instanceof Local){
res.add(new DataFlowAbstraction((Local) valueBox.getValue(), stmt));
} else if (valueBox.getValue() instanceof ArrayRef) {
} else if (valueBox.getValue() instanceof ArrayRef){
res.add(new DataFlowAbstraction(getArrayName(valueBox), stmt));
} else if (valueBox.getValue() instanceof StaticFieldRef) {
} else if (valueBox.getValue() instanceof StaticFieldRef) {
res.add(new DataFlowAbstraction((StaticFieldRef) valueBox.getValue(), stmt));
} else if (valueBox.getValue() instanceof InstanceFieldRef) {
} else if (valueBox.getValue() instanceof InstanceFieldRef){
res.add(new DataFlowAbstraction(getFieldName(valueBox), stmt));
}
});
Expand Down Expand Up @@ -125,10 +126,18 @@ protected void detectConflict(FlowSet<DataFlowAbstraction> in, Unit u) {
private void checkConflicts(Unit u, List<DataFlowAbstraction> potentialConflictingAssignments) {
for (DataFlowAbstraction dataFlowAbstraction : potentialConflictingAssignments) {
if (abstractionVariableIsInIUnitDefBoxes(dataFlowAbstraction, u)) {
Conflict c = new Conflict(dataFlowAbstraction.getStmt(), findStatement(u));
Collector.instance().addConflict(c);
reportConflict(dataFlowAbstraction.getStmt(), u);
}
}
//Report conflict when changing the same return
if (u instanceof ReturnStmt && isLeftStatement(u) && isRightStatement(u)){
reportConflict(findStatement(u), u);
}
}

private void reportConflict(Statement left, Unit right){
Conflict c = new Conflict(left, findStatement(right));
Collector.instance().addConflict(c);
}

/*
Expand All @@ -138,17 +147,58 @@ private void checkConflicts(Unit u, List<DataFlowAbstraction> potentialConflicti
private boolean abstractionVariableIsInIUnitDefBoxes(DataFlowAbstraction dataFlowAbstraction, Unit u) {
for (ValueBox valueBox : u.getDefBoxes()) {
Object value = valueBox.getValue();
if (value instanceof InstanceFieldRef && dataFlowAbstraction.getFieldRef() != null) {
if (value instanceof InstanceFieldRef && dataFlowAbstraction.getFieldRef()!=null) {
return dataFlowAbstraction.getFieldRef().toString().equals(getFieldsChain(value.toString()));
} else if (value instanceof ArrayRef && value.toString().contains("$stack")) { // If contain $stack, contain a array chain
return getVarNameFromAbstraction(dataFlowAbstraction).equals(getArrayChain(valueBox));
} else {
} else{
return getVarNameFromAbstraction(dataFlowAbstraction).equals(getVarNameFromValueBox(valueBox));
}
}
if (u instanceof InvokeStmt){
return compareMethodAndObjectName(dataFlowAbstraction, u);
}
return false;
}

/*
* Compares whether left and right called the same object and method
*/
private boolean compareMethodAndObjectName(DataFlowAbstraction dataFlowAbstraction, Unit u){
if ( !(dataFlowAbstraction.getStmt().getUnit() instanceof InvokeStmt)){
return false;
}
String objectNameFromUnit = getObjectName(u);
String methodStatementFromUnit = getMethodName(u);

String objectNameFromAbstraction = getObjectName(dataFlowAbstraction.getStmt().getUnit());
String methodStatementFromAbstraction = getMethodName(dataFlowAbstraction.getStmt().getUnit());

String methodName = (((InvokeStmt) u).getInvokeExpr()).getMethodRef().getName();

if ((objectNameFromUnit+""+methodStatementFromUnit).equals(objectNameFromAbstraction+""+methodStatementFromAbstraction) && !methodName.startsWith("get")){
return true;
}
return false;
}

/*
* Returns a String containing the name of the object given a Unit
*/
private String getObjectName(Unit u){
if (u instanceof VirtualInvokeExpr){
return ((VirtualInvokeExpr)((InvokeStmt) u).getInvokeExpr()).getBase().toString();
}
return "";
}

/*
* Returns a String containing the name of the method called given a Unit
*/
private String getMethodName(Unit u){
return (((InvokeStmt) u).getInvokeExpr()).getMethodRef().toString();
}

/*
* Returns a String containing the name of the variable given a DataFlowAbstraction
*/
Expand Down Expand Up @@ -212,11 +262,11 @@ private Value getArrayRefName(ArrayRef arrayRef) {
/*
* If it's a InstanceField, returns your complete name from the hashMapInstanceField
*/
private InstanceFieldRef getFieldName(ValueBox valueBox) {
private InstanceFieldRef getFieldName(ValueBox valueBox){
InstanceFieldRef fieldValue = (InstanceFieldRef) valueBox.getValue();
if (fieldValue.toString().contains("$stack")) {
String chainName = getFieldsChain(valueBox.getValue().toString()); //return the complete chain with the FieldRef
((Local) fieldValue.getBase()).setName(chainName.replace("." + fieldValue.getField().toString(), "")); //remove the double FieldRef from jInstanceFieldValue
((Local) fieldValue.getBase()).setName(chainName.replace("."+fieldValue.getField().toString(), "")); //remove the double FieldRef from jInstanceFieldValue
}
return fieldValue;
}
Expand Down Expand Up @@ -276,23 +326,19 @@ private String getArrayChain(ValueBox valueBox){
* Class object = new Class();
* object.b.a.a = object.b.b.a + 3;
* Jimple:
* $stack2 = new Class;
* object = $stack2;
* $stack3 = object.b;
* $stack8 = $stack3.a;
* $stack7 = $stack6 + 3;
* $stack8.a = $stack7; //$stack8.a is the nextKey of the call object.b.a.a
* The result is:
* $stack8.a -> $stack8 = $stack3.a; -> $stack3 = object.b; -> object.b; (STOP) -> Return object chain
* InitialKey($stack8.a) -> nextKey ($stack8) -> nextKey ($stack3) -> object.b has no nextKey (STOP) -> Return object chain -> Return: object.b.a.a
*/
private String getFieldsChain(String nextKey){
List<HashMap<String, InstanceFieldRef>> auxValuesHashMap = new ArrayList<>();
auxValuesHashMap.addAll(getHashMapJInstanceField());
auxValuesHashMap.addAll(getHashMapInstanceField());

//If nextKey not contain $stack is because simple key
if (!(nextKey.contains("$stack"))){
Expand Down Expand Up @@ -345,7 +391,7 @@ public void generateFieldDictionary(Unit u){
for (ValueBox valueBox: u.getUseBoxes()) {
if (valueBox.getValue() instanceof InstanceFieldRef) {
generateClassFieldDictionary(getStatementAssociatedWithUnit(u));
} else if (valueBox.getValue() instanceof StaticFieldRef) {
}else if (valueBox.getValue() instanceof StaticFieldRef) {
generateStaticRefDictionary(u, valueBox);
}
}
Expand Down
55 changes: 28 additions & 27 deletions src/main/java/br/unb/cic/analysis/df/ReachDefinitionAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import soot.jimple.ArrayRef;
import soot.jimple.InstanceFieldRef;
import soot.jimple.StaticFieldRef;
import soot.jimple.internal.JInstanceFieldRef;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.scalar.ArraySparseSet;
import soot.toolkits.scalar.FlowSet;
Expand Down Expand Up @@ -48,7 +49,7 @@ public ReachDefinitionAnalysis(Body methodBody, AbstractMergeConflictDefinition
definition.loadSinkStatements();
doAnalysis();
}

/**
* Runs the algorithm analysis at a given statement (Unit d). Here we
* manipulate and compute an out set from the income set in (foward analysis).
Expand Down Expand Up @@ -175,44 +176,44 @@ protected boolean isSourceStatement(Unit d) {

protected boolean isSinkStatement(Unit d) {
return definition.getSinkStatements().stream().map(s -> s.getUnit()).collect(Collectors.toList()).contains(d);
}
}

public void clear() {
Collector.instance().clear();
}
public void clear() {
Collector.instance().clear();
}

public Set<Conflict> getConflicts() {
return Collector.instance().getConflicts();
}
public Set<Conflict> getConflicts() {
return Collector.instance().getConflicts();
}

public Set<HashMap<String, InstanceFieldRef>> getHashMapJInstanceField() {
return Collector.instance().getHashInstanceField();
}
public Set<HashMap<String, InstanceFieldRef>> getHashMapInstanceField() {
return Collector.instance().getHashInstanceField();
}

public Set<HashMap<String, StaticFieldRef>> getHashMapStatic() {
return Collector.instance().getHashStaticField();
}
public Set<HashMap<String, StaticFieldRef>> getHashMapStatic() {
return Collector.instance().getHashStaticField();
}

protected List<Local> getUseVariables(Unit u) {
return u.getUseBoxes().stream()
.map(box -> box.getValue())
.filter(v -> v instanceof Local)
protected List<Local> getUseVariables(Unit u) {
return u.getUseBoxes().stream()
.map(box -> box.getValue())
.filter(v -> v instanceof Local)
.map(v -> (Local)v)
.collect(Collectors.toList());
}

protected List<Local> getDefVariables(Unit u) {
List<Local> localDefs = new ArrayList<>();
for (ValueBox v : u.getDefBoxes()) {
if (v.getValue() instanceof Local) {
localDefs.add((Local) v.getValue());
} else if (v.getValue() instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) v.getValue();
localDefs.add((Local) ref.getBaseBox().getValue());
} else if (v.getValue() instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) v.getValue();
localDefs.add((Local) ref.getBaseBox().getValue());
}
if (v.getValue() instanceof Local) {
localDefs.add((Local) v.getValue());
} else if (v.getValue() instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) v.getValue();
localDefs.add((Local) ref.getBaseBox().getValue());
} else if (v.getValue() instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) v.getValue();
localDefs.add((Local) ref.getBaseBox().getValue());
}
}
return localDefs;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package br.unb.cic.analysis.df;

import br.unb.cic.analysis.AbstractMergeConflictDefinition;
import br.unb.cic.analysis.SootWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import soot.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OverridingAssignmentAnalysisMethodCallConflictTest {

private OverridingAssignmentAnalysis analysis;

@Before
public void configure() {
G.reset();
Collector.instance().clear();

AbstractMergeConflictDefinition definition = new AbstractMergeConflictDefinition() {
@Override
protected Map<String, List<Integer>> sourceDefinitions() {
Map<String, List<Integer>> res = new HashMap<>();
List<Integer> lines = new ArrayList<>();
lines.add(7); //left
lines.add(10); //left
res.put("br.unb.cic.analysis.samples.OverridingAssignmentMethodCallSample", lines);
return res;
}

@Override
protected Map<String, List<Integer>> sinkDefinitions() {
Map<String, List<Integer>> res = new HashMap<>();
List<Integer> lines = new ArrayList<>();
lines.add(9); //right
res.put("br.unb.cic.analysis.samples.OverridingAssignmentMethodCallSample", lines);
return res;
}
};

PackManager.v().getPack("jtp").add(
new Transform("jtp.oneConflict", new BodyTransformer() {
@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
analysis = new OverridingAssignmentAnalysis(body, definition);
}
}));
String cp = "target/test-classes";
String targetClass = "br.unb.cic.analysis.samples.OverridingAssignmentMethodCallSample";
PhaseOptions.v().setPhaseOption("jb", "use-original-names:true");

SootWrapper.builder().withClassPath(cp).addClass(targetClass).build().execute();
}

@Test
public void testDataFlowAnalysisExpectingOneConflict() {
Assert.assertEquals(1, analysis.getConflicts().size());
}
}
Loading

0 comments on commit 49bc5fa

Please sign in to comment.