boomerang.flowfunction.DefaultBackwardFlowFunction Maven / Gradle / Ivy
package boomerang.flowfunction;
import boomerang.BoomerangOptions;
import boomerang.scene.ControlFlowGraph.Edge;
import boomerang.scene.Field;
import boomerang.scene.InvokeExpr;
import boomerang.scene.Method;
import boomerang.scene.Pair;
import boomerang.scene.Statement;
import boomerang.scene.StaticFieldVal;
import boomerang.scene.Val;
import boomerang.solver.BackwardBoomerangSolver;
import boomerang.solver.Strategies;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import sync.pds.solver.SyncPDSSolver.PDSSystem;
import sync.pds.solver.nodes.ExclusionNode;
import sync.pds.solver.nodes.Node;
import sync.pds.solver.nodes.NodeWithLocation;
import sync.pds.solver.nodes.PopNode;
import sync.pds.solver.nodes.PushNode;
import wpds.impl.Weight;
import wpds.interfaces.State;
public class DefaultBackwardFlowFunction implements IBackwardFlowFunction {
private final BoomerangOptions options;
private Strategies strategies;
private BackwardBoomerangSolver solver;
public DefaultBackwardFlowFunction(BoomerangOptions opts) {
this.options = opts;
}
@Override
public Collection returnFlow(Method callee, Statement returnStmt, Val returnedVal) {
Set out = Sets.newHashSet();
if (!callee.isStatic()) {
if (callee.getThisLocal().equals(returnedVal)) {
out.add(returnedVal);
}
}
for (Val param : callee.getParameterLocals()) {
if (param.equals(returnedVal)) {
out.add(returnedVal);
}
}
if (callee.isStatic()) {
out.add(returnedVal);
}
return out;
}
@Override
public Collection callFlow(Statement callSite, Val fact, Method callee, Statement calleeSp) {
if (!callSite.containsInvokeExpr()) {
throw new RuntimeException("Call site does not contain an invoke expression.");
}
InvokeExpr invokeExpr = callSite.getInvokeExpr();
Set out = Sets.newHashSet();
if (invokeExpr.isInstanceInvokeExpr()) {
if (invokeExpr.getBase().equals(fact) && !callee.isStatic()) {
out.add(callee.getThisLocal());
}
}
List parameterLocals = callee.getParameterLocals();
int i = 0;
for (Val arg : invokeExpr.getArgs()) {
if (arg.equals(fact) && parameterLocals.size() > i) {
Val param = parameterLocals.get(i);
out.add(param);
}
i++;
}
if (callSite.isAssign() && calleeSp.isReturnStmt()) {
if (callSite.getLeftOp().equals(fact)) {
out.add(calleeSp.getReturnOp());
}
}
if (fact.isStatic()) {
out.add(fact.withNewMethod(callee));
}
return out;
}
@Override
public Collection normalFlow(Edge currEdge, Val fact) {
Statement curr = currEdge.getTarget();
if (options.getAllocationVal(curr.getMethod(), curr, fact).isPresent()) {
return Collections.emptySet();
}
if (curr.isThrowStmt()) {
return Collections.emptySet();
}
Set out = Sets.newHashSet();
boolean leftSideMatches = false;
if (curr.isAssign()) {
Val leftOp = curr.getLeftOp();
Val rightOp = curr.getRightOp();
if (leftOp.equals(fact)) {
leftSideMatches = true;
if (curr.isFieldLoad()) {
if (options.trackFields()) {
Pair ifr = curr.getFieldLoad();
if (!options.ignoreInnerClassFields() || !ifr.getY().isInnerClassField()) {
out.add(new PushNode<>(currEdge, ifr.getX(), ifr.getY(), PDSSystem.FIELDS));
}
}
} else if (curr.isStaticFieldLoad()) {
if (options.trackFields()) {
strategies
.getStaticFieldStrategy()
.handleBackward(currEdge, curr.getLeftOp(), curr.getStaticField(), out);
}
} else if (rightOp.isArrayRef()) {
Pair arrayBase = curr.getArrayBase();
if (options.trackFields()) {
strategies.getArrayHandlingStrategy().handleBackward(currEdge, arrayBase, out);
}
} else if (rightOp.isCast()) {
out.add(new Node<>(currEdge, rightOp.getCastOp()));
} else if (curr.isPhiStatement()) {
Collection phiVals = curr.getPhiVals();
for (Val v : phiVals) {
out.add(new Node<>(currEdge, v));
}
} else {
if (curr.isFieldLoadWithBase(fact)) {
out.add(new ExclusionNode<>(currEdge, fact, curr.getLoadedField()));
} else {
out.add(new Node<>(currEdge, rightOp));
}
}
}
if (curr.isFieldStore()) {
Pair ifr = curr.getFieldStore();
Val base = ifr.getX();
if (base.equals(fact)) {
NodeWithLocation succNode =
new NodeWithLocation<>(currEdge, rightOp, ifr.getY());
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
} else if (curr.isStaticFieldStore()) {
StaticFieldVal staticField = curr.getStaticField();
if (fact.isStatic() && fact.equals(staticField)) {
out.add(new Node<>(currEdge, rightOp));
}
} else if (leftOp.isArrayRef()) {
Pair arrayBase = curr.getArrayBase();
if (arrayBase.getX().equals(fact)) {
NodeWithLocation succNode =
new NodeWithLocation<>(currEdge, rightOp, Field.array(arrayBase.getY()));
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
}
}
if (!leftSideMatches) out.add(new Node<>(currEdge, fact));
return out;
}
@Override
public Collection callToReturnFlow(Edge edge, Val fact) {
if (FlowFunctionUtils.isSystemArrayCopy(edge.getTarget().getInvokeExpr().getMethod())) {
return systemArrayCopyFlow(edge, fact);
}
return normalFlow(edge, fact);
}
@Override
public void setSolver(
BackwardBoomerangSolver solver,
Multimap fieldLoadStatements,
Multimap fieldStoreStatements) {
this.solver = solver;
this.strategies = new Strategies<>(options, solver, fieldLoadStatements, fieldStoreStatements);
}
protected Collection systemArrayCopyFlow(Edge edge, Val fact) {
Statement callSite = edge.getTarget();
if (fact.equals(callSite.getInvokeExpr().getArg(2))) {
Val arg = callSite.getInvokeExpr().getArg(0);
return Collections.singleton(new Node<>(edge, arg));
}
return Collections.emptySet();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy