boomerang.poi.CopyAccessPathChain Maven / Gradle / Ivy
package boomerang.poi;
import boomerang.BackwardQuery;
import boomerang.scene.ControlFlowGraph.Edge;
import boomerang.scene.Field;
import boomerang.scene.Statement;
import boomerang.scene.Val;
import boomerang.solver.BackwardBoomerangSolver;
import boomerang.solver.ForwardBoomerangSolver;
import com.google.common.base.Objects;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.Set;
import sync.pds.solver.nodes.INode;
import sync.pds.solver.nodes.Node;
import sync.pds.solver.nodes.SingleNode;
import wpds.impl.Transition;
import wpds.impl.Weight;
import wpds.impl.WeightedPAutomaton;
import wpds.interfaces.WPAStateListener;
public class CopyAccessPathChain {
private static final int MAX_WALK_DEPTH = -1;
private ForwardBoomerangSolver forwardSolver;
private BackwardBoomerangSolver backwardSolver;
private Edge fieldWriteStatement;
// TODO: Source of non-determinsim: not part of hashCode/equals....but also shall not be.
private INode> killedTransitionTarget;
public CopyAccessPathChain(
ForwardBoomerangSolver forwardSolver,
BackwardBoomerangSolver backwardSolver,
Edge fieldWriteStatement,
Transition>> killedTransition) {
this.forwardSolver = forwardSolver;
this.backwardSolver = backwardSolver;
this.fieldWriteStatement = fieldWriteStatement;
this.killedTransitionTarget = killedTransition.getTarget();
}
public void exec() {
forwardSolver
.getFieldAutomaton()
.registerListener(
new WalkForwardSolverListener(
killedTransitionTarget,
new SingleNode<>(
new Node<>(fieldWriteStatement, fieldWriteStatement.getTarget().getRightOp())),
0));
}
private class WalkForwardSolverListener
extends WPAStateListener>, W> {
private INode> stateInBwSolver;
private int walkDepth;
public WalkForwardSolverListener(
INode> target, INode> stateInBwSolver, int walkDepth) {
super(target);
this.stateInBwSolver = stateInBwSolver;
this.walkDepth = walkDepth;
}
@Override
public void onOutTransitionAdded(
Transition>> t,
W w,
WeightedPAutomaton>, W> weightedPAutomaton) {
if (t.getLabel().equals(Field.empty())) {
if (forwardSolver.getFieldAutomaton().isUnbalancedState(t.getTarget())) {
if (t.getStart().equals(CopyAccessPathChain.this.killedTransitionTarget)) {
// Do a simple backwardSolve(...)...
BackwardQuery query =
BackwardQuery.make(
fieldWriteStatement, fieldWriteStatement.getTarget().getRightOp());
INode> fieldTarget = backwardSolver.createQueryNodeField(query);
INode callTarget =
backwardSolver.generateCallState(new SingleNode<>(query.var()), query.cfgEdge());
backwardSolver.solve(
query.asNode(), Field.empty(), fieldTarget, query.cfgEdge(), callTarget);
return;
}
// addReachable(stateInBwSolver);
}
return;
}
INode> targetState =
backwardSolver.generateFieldState(
new SingleNode<>(
new Node<>(new Edge(Statement.epsilon(), Statement.epsilon()), Val.zero())),
t.getLabel());
Transition>> insert =
new Transition<>(stateInBwSolver, t.getLabel(), targetState);
queueOrAdd(insert);
int newDepth = walkDepth + 1;
if (MAX_WALK_DEPTH < 0 || newDepth < MAX_WALK_DEPTH) {
forwardSolver
.getFieldAutomaton()
.registerListener(new WalkForwardSolverListener(t.getTarget(), targetState, newDepth));
}
}
@Override
public void onInTransitionAdded(
Transition>> t,
W w,
WeightedPAutomaton>, W> weightedPAutomaton) {}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WalkForwardSolverListener that = (WalkForwardSolverListener) o;
if (!getEnclosingInstance().equals(that.getEnclosingInstance())) return false;
return Objects.equal(stateInBwSolver, that.stateInBwSolver);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + ((stateInBwSolver == null) ? 0 : stateInBwSolver.hashCode());
return result;
}
private CopyAccessPathChain getEnclosingInstance() {
return CopyAccessPathChain.this;
}
}
// Copied from ExecuteImportFielStmtPOI
private Set>> reachable = Sets.newHashSet();
private Multimap>, InsertFieldTransitionCallback> delayedTransitions =
HashMultimap.create();
public void addReachable(INode> node) {
if (reachable.add(node)) {
for (InsertFieldTransitionCallback callback :
Lists.newArrayList(delayedTransitions.get(node))) {
callback.trigger();
}
}
}
private void queueOrAdd(Transition>> transToInsert) {
if (reachable.contains(transToInsert.getTarget())) {
backwardSolver.getFieldAutomaton().addTransition(transToInsert);
} else {
delayedTransitions.put(
transToInsert.getTarget(), new InsertFieldTransitionCallback(transToInsert));
}
}
private class InsertFieldTransitionCallback {
private final Transition>> trans;
public InsertFieldTransitionCallback(Transition>> trans) {
this.trans = trans;
}
public void trigger() {
backwardSolver.getFieldAutomaton().addTransition(trans);
addReachable(trans.getStart());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + ((trans == null) ? 0 : trans.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
InsertFieldTransitionCallback other = (InsertFieldTransitionCallback) obj;
if (!getEnclosingInstance().equals(other.getEnclosingInstance())) return false;
if (trans == null) {
if (other.trans != null) return false;
} else if (!trans.equals(other.trans)) return false;
return true;
}
private CopyAccessPathChain getEnclosingInstance() {
return CopyAccessPathChain.this;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((backwardSolver == null) ? 0 : backwardSolver.hashCode());
result = prime * result + ((fieldWriteStatement == null) ? 0 : fieldWriteStatement.hashCode());
result = prime * result + ((forwardSolver == null) ? 0 : forwardSolver.hashCode());
result =
prime * result + ((killedTransitionTarget == null) ? 0 : killedTransitionTarget.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
CopyAccessPathChain other = (CopyAccessPathChain) obj;
if (backwardSolver == null) {
if (other.backwardSolver != null) return false;
} else if (!backwardSolver.equals(other.backwardSolver)) return false;
if (fieldWriteStatement == null) {
if (other.fieldWriteStatement != null) return false;
} else if (!fieldWriteStatement.equals(other.fieldWriteStatement)) return false;
if (forwardSolver == null) {
if (other.forwardSolver != null) return false;
} else if (!forwardSolver.equals(other.forwardSolver)) return false;
if (killedTransitionTarget == null) {
if (other.killedTransitionTarget != null) return false;
} else if (!killedTransitionTarget.equals(other.killedTransitionTarget)) return false;
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy