All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boomerang.poi.ExecuteImportFieldStmtPOI Maven / Gradle / Ivy

There is a newer version: 3.2.2
Show newest version
package boomerang.poi;

import boomerang.scene.ControlFlowGraph.Edge;
import boomerang.scene.Field;
import boomerang.scene.Statement;
import boomerang.scene.Val;
import boomerang.solver.AbstractBoomerangSolver;
import boomerang.solver.ControlFlowEdgeBasedCallTransitionListener;
import boomerang.solver.ControlFlowEdgeBasedFieldTransitionListener;
import boomerang.solver.ForwardBoomerangSolver;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sync.pds.solver.nodes.GeneratedState;
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;
import wpds.interfaces.WPAUpdateListener;

public abstract class ExecuteImportFieldStmtPOI {
  private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteImportFieldStmtPOI.class);
  private static final int MAX_IMPORT_DEPTH = -1;
  private Set>> reachable = Sets.newHashSet();
  private Multimap>, InsertFieldTransitionCallback> delayedTransitions =
      HashMultimap.create();
  protected final ForwardBoomerangSolver baseSolver;
  protected final ForwardBoomerangSolver flowSolver;
  protected final Edge curr;
  protected final WeightedPAutomaton>, W> baseAutomaton;
  protected final WeightedPAutomaton>, W> flowAutomaton;
  private final Val baseVar;
  private final Val storedVar;
  private final Field field;
  boolean active = false;

  public ExecuteImportFieldStmtPOI(
      final ForwardBoomerangSolver baseSolver,
      ForwardBoomerangSolver flowSolver,
      AbstractPOI poi) {
    this.baseSolver = baseSolver;
    this.flowSolver = flowSolver;
    this.baseAutomaton = baseSolver.getFieldAutomaton();
    this.flowAutomaton = flowSolver.getFieldAutomaton();
    this.curr = poi.getCfgEdge();
    this.baseVar = poi.getBaseVar();
    this.storedVar = poi.getStoredVar();
    this.field = poi.getField();
  }

  private boolean isLogEnabled() {
    return true;
  }

  private final class ImportTransitionFromCall
      extends ControlFlowEdgeBasedCallTransitionListener {

    private final INode start;
    private AbstractBoomerangSolver flowSolver;
    private INode target;
    private W w;

    public ImportTransitionFromCall(
        AbstractBoomerangSolver flowSolver,
        Edge stmt,
        INode start,
        INode target,
        W w) {
      super(stmt);
      this.start = start;
      this.flowSolver = flowSolver;
      this.target = target;
      this.w = w;
    }

    @Override
    public void onAddedTransition(Transition> t, W w) {
      if (t.getStart() instanceof GeneratedState) return;
      Transition> newTrans = new Transition<>(t.getStart(), t.getLabel(), target);
      if (isLogEnabled()) {
        LOGGER.trace("Copying {} to {}", newTrans, flowSolver);
      }
      if (!t.getStart().equals(start)) {
        if (t.getStart().fact().m().equals(t.getLabel().getStart().getMethod())) {
          // To compute the right Data-Flow Path, apparently, Weight.ONE is necessary and the
          // following line works.
          // flowSolver.getCallAutomaton().addTransition(newTrans);
          // For IDEAL the Weight this.w must be carried along:
          // FileMustBeClosedTest.flowViaFieldDirect
          flowSolver.getCallAutomaton().addWeightForTransition(newTrans, this.w);
        }
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      result = prime * result + ((target == null) ? 0 : target.hashCode());
      result = prime * result + ((w == null) ? 0 : w.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;
      ImportTransitionFromCall other = (ImportTransitionFromCall) obj;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else if (!flowSolver.equals(other.flowSolver)) return false;
      if (target == null) {
        if (other.target != null) return false;
      } else if (!target.equals(other.target)) return false;
      if (w == null) {
        if (other.w != null) return false;
      } else if (!w.equals(other.w)) return false;
      return true;
    }
  }

  private final class ImportOnReachStatement extends ControlFlowEdgeBasedCallTransitionListener {
    private AbstractBoomerangSolver flowSolver;

    private ImportOnReachStatement(AbstractBoomerangSolver flowSolver, Edge callSiteOrExitStmt) {
      super(callSiteOrExitStmt);
      this.flowSolver = flowSolver;
    }

    @Override
    public void onAddedTransition(Transition> t, W w) {
      if (t.getStart() instanceof GeneratedState) {
        return;
      }
      if (t.getLabel().equals(getControlFlowEdge())) {
        baseSolver.registerStatementFieldTransitionListener(
            new CallSiteOrExitStmtFieldImport(
                flowSolver, baseSolver, new Node<>(t.getLabel(), t.getStart().fact())));
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      ImportOnReachStatement other = (ImportOnReachStatement) obj;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else if (!flowSolver.equals(other.flowSolver)) return false;
      return true;
    }
  }

  private class ForAnyCallSiteOrExitStmt implements WPAUpdateListener, W> {
    private AbstractBoomerangSolver baseSolver;

    public ForAnyCallSiteOrExitStmt(AbstractBoomerangSolver baseSolver) {
      this.baseSolver = baseSolver;
    }

    @Override
    public void onWeightAdded(
        Transition> t, W w, WeightedPAutomaton, W> aut) {
      if (!flowSolver.getCallAutomaton().isUnbalancedState(t.getTarget())) return;
      if (t.getLabel().equals(new Edge(Statement.epsilon(), Statement.epsilon()))) {
        return;
      }
      Edge edge = t.getLabel();
      Statement callSite = edge.getStart();
      /*  if (t.getStart().fact() instanceof AllocVal) {
        if (((AllocVal) t.getStart().fact())
            .getDelegate()
            .equals(t.getTarget().fact().asUnbalanced(null))) {
          return;
        }
      } else if (t.getStart()
          .fact()
          .asUnbalanced(null)
          .equals(t.getTarget().fact().asUnbalanced(null))) return;*/
      if (callSite.containsInvokeExpr()) {
        if (callSite.isAssign() && callSite.getLeftOp().equals(t.getStart().fact())) return;
        if (callSite.uses(t.getStart().fact())) {
          importSolvers(edge, t.getStart(), t.getTarget(), w);
        }
      }
    }

    private void importSolvers(Edge callSiteOrExitStmt, INode start, INode node, W w) {
      if (isLogEnabled()) {
        LOGGER.trace(
            "Importing solvers at {} from {} to {}", callSiteOrExitStmt, baseSolver, flowSolver);
      }
      baseSolver.registerStatementCallTransitionListener(
          new ImportOnReachStatement(flowSolver, callSiteOrExitStmt));
      baseSolver.registerStatementCallTransitionListener(
          new ImportTransitionFromCall(flowSolver, callSiteOrExitStmt, start, node, w));
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((baseSolver == null) ? 0 : baseSolver.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;
      ForAnyCallSiteOrExitStmt other = (ForAnyCallSiteOrExitStmt) obj;
      if (baseSolver == null) {
        if (other.baseSolver != null) return false;
      } else if (!baseSolver.equals(other.baseSolver)) return false;
      return true;
    }
  }

  public void solve() {
    if (baseSolver.equals(flowSolver)) {
      return;
    }
    baseSolver.registerStatementFieldTransitionListener(new BaseVarPointsTo(curr, this));
  }

  private class BaseVarPointsTo extends ControlFlowEdgeBasedFieldTransitionListener {

    private ExecuteImportFieldStmtPOI poi;

    public BaseVarPointsTo(Edge curr, ExecuteImportFieldStmtPOI executeImportFieldStmtPOI) {
      super(curr);
      this.poi = executeImportFieldStmtPOI;
    }

    @Override
    public void onAddedTransition(Transition>> t) {
      final INode> aliasedVariableAtStmt = t.getStart();
      if (active) return;
      if (!(aliasedVariableAtStmt instanceof GeneratedState)) {
        Val alias = aliasedVariableAtStmt.fact().fact();
        if (alias.equals(poi.baseVar) && t.getLabel().equals(Field.empty())) {
          flowsTo();
        }
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((poi == null) ? 0 : poi.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      BaseVarPointsTo other = (BaseVarPointsTo) obj;
      if (poi == null) {
        if (other.poi != null) return false;
      } else if (!poi.equals(other.poi)) return false;
      return true;
    }
  }

  protected void flowsTo() {
    if (active) return;
    active = true;
    if (isLogEnabled()) {
      LOGGER.trace("POI: Propagation of {} flows to {}", baseSolver, flowSolver);
    }
    handlingAtFieldStatements();
    handlingAtCallSites();
  }

  private void handlingAtFieldStatements() {
    baseSolver.registerStatementFieldTransitionListener(
        new ImportIndirectAliases(curr, this.flowSolver, this.baseSolver));
    flowSolver.registerStatementCallTransitionListener(
        new ImportIndirectCallAliases(curr, this.flowSolver));
  }

  private void handlingAtCallSites() {
    flowSolver.getCallAutomaton().registerListener(new ForAnyCallSiteOrExitStmt(this.baseSolver));
  }

  private final class ImportIndirectCallAliases
      extends ControlFlowEdgeBasedCallTransitionListener {

    private AbstractBoomerangSolver flowSolver;

    public ImportIndirectCallAliases(Edge stmt, AbstractBoomerangSolver flowSolver) {
      super(stmt);
      this.flowSolver = flowSolver;
    }

    @Override
    public void onAddedTransition(Transition> t, W w) {
      if (t.getStart().fact().equals(storedVar)) {
        baseSolver.registerStatementCallTransitionListener(
            new ImportIndirectCallAliasesAtSucc(curr, t.getTarget(), w));
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      ImportIndirectCallAliases other = (ImportIndirectCallAliases) obj;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else if (!flowSolver.equals(other.flowSolver)) return false;
      return true;
    }
  }

  private final class ImportIndirectCallAliasesAtSucc
      extends ControlFlowEdgeBasedCallTransitionListener {

    private INode target;
    private W w;

    public ImportIndirectCallAliasesAtSucc(Edge succ, INode target, W w) {
      super(succ);
      this.target = target;
      this.w = w;
    }

    @Override
    public void onAddedTransition(Transition> t, W w) {
      if (getControlFlowEdge().getStart().isFieldStore()
          && !getControlFlowEdge().getStart().getFieldStore().getX().equals(t.getStart().fact())) {
        flowSolver
            .getCallAutomaton()
            .addWeightForTransition(new Transition<>(t.getStart(), t.getLabel(), target), this.w);
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((target == null) ? 0 : target.hashCode());
      result = prime * result + ((w == null) ? 0 : w.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      ImportIndirectCallAliasesAtSucc other = (ImportIndirectCallAliasesAtSucc) obj;
      if (target == null) {
        if (other.target != null) return false;
      } else if (!target.equals(other.target)) return false;
      if (w == null) {
        if (other.w != null) return false;
      } else if (!w.equals(other.w)) return false;
      return true;
    }
  }

  private final class ImportIndirectAliases extends ControlFlowEdgeBasedFieldTransitionListener {

    private AbstractBoomerangSolver flowSolver;
    private AbstractBoomerangSolver baseSolver;

    public ImportIndirectAliases(
        Edge succ, AbstractBoomerangSolver flowSolver, AbstractBoomerangSolver baseSolver) {
      super(succ);
      this.flowSolver = flowSolver;
      this.baseSolver = baseSolver;
    }

    @Override
    public void onAddedTransition(Transition>> t) {
      if (t.getLabel().equals(Field.epsilon())) {
        return;
      }
      if (!(t.getStart() instanceof GeneratedState)) {
        importFieldTransitionsStartingAt(t, 0);
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((baseSolver == null) ? 0 : baseSolver.hashCode());
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      ImportIndirectAliases other = (ImportIndirectAliases) obj;
      if (baseSolver == null) {
        if (other.baseSolver != null) return false;
      } else if (!baseSolver.equals(other.baseSolver)) return false;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else return flowSolver.equals(other.flowSolver);
      return true;
    }
  }

  private final class CallSiteOrExitStmtFieldImport
      extends ControlFlowEdgeBasedFieldTransitionListener {

    private AbstractBoomerangSolver flowSolver;
    private AbstractBoomerangSolver baseSolver;
    private Val fact;

    private CallSiteOrExitStmtFieldImport(
        AbstractBoomerangSolver flowSolver,
        AbstractBoomerangSolver baseSolver,
        Node reachableNode) {
      super(reachableNode.stmt());
      this.flowSolver = flowSolver;
      this.baseSolver = baseSolver;
      this.fact = reachableNode.fact();
    }

    @Override
    public void onAddedTransition(Transition>> innerT) {
      if (innerT.getLabel().equals(Field.epsilon())) {
        return;
      }
      if (!(innerT.getStart() instanceof GeneratedState)
          && innerT.getStart().fact().fact().equals(fact)) {
        importFieldTransitionsStartingAt(innerT, 0);
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((baseSolver == null) ? 0 : baseSolver.hashCode());
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      result = prime * result + ((fact == null) ? 0 : fact.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      CallSiteOrExitStmtFieldImport other = (CallSiteOrExitStmtFieldImport) obj;
      if (baseSolver == null) {
        if (other.baseSolver != null) return false;
      } else if (!baseSolver.equals(other.baseSolver)) return false;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else if (!flowSolver.equals(other.flowSolver)) return false;
      if (fact == null) {
        if (other.fact != null) return false;
      } else if (!fact.equals(other.fact)) return false;
      return true;
    }
  }

  protected void importFieldTransitionsStartingAt(
      Transition>> t, int importDepth) {
    if (MAX_IMPORT_DEPTH > 0 && importDepth > MAX_IMPORT_DEPTH) return;
    if (t.getLabel().equals(Field.epsilon())) {
      return;
    }
    if (t.getLabel().equals(Field.empty())) {
      if (isLogEnabled()) {
        LOGGER.trace("Activating with {}", t.getStart());
      }
      if (baseSolver.getFieldAutomaton().isUnbalancedState(t.getTarget())) {
        activate(t.getStart());
      }
    } else if (t.getTarget() instanceof GeneratedState) {
      if (isLogEnabled()) {
        LOGGER.trace("Copying {} into Field Automaton {}", t, flowSolver);
      }
      queueOrAdd(t);
      int newDepth = importDepth + 1;
      baseSolver
          .getFieldAutomaton()
          .registerListener(
              new ImportFieldTransitionsFrom(t.getTarget(), this.flowSolver, newDepth));
    }
  }

  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())) {
      flowSolver.getFieldAutomaton().addTransition(transToInsert);
      addReachable(transToInsert.getStart());
    } else {
      delayedTransitions.put(
          transToInsert.getTarget(), new InsertFieldTransitionCallback(transToInsert));
    }
  }

  public abstract void activate(INode> start);

  public void trigger(INode> start) {
    INode> intermediateState =
        flowSolver
            .getFieldAutomaton()
            .createState(new SingleNode<>(new Node<>(curr, baseVar)), field);
    Transition>> connectingTrans =
        new Transition<>(start, field, intermediateState);
    if (isLogEnabled()) {
      LOGGER.trace("Connecting {} into Field Automaton {}", connectingTrans, flowSolver);
    }
    flowSolver.getFieldAutomaton().addTransition(connectingTrans);
    addReachable(connectingTrans.getStart());
  }

  private final class ImportFieldTransitionsFrom
      extends WPAStateListener>, W> {

    private AbstractBoomerangSolver flowSolver;
    private int importDepth;

    public ImportFieldTransitionsFrom(
        INode> target, AbstractBoomerangSolver flowSolver, int importDepth) {
      super(target);
      this.flowSolver = flowSolver;
      this.importDepth = importDepth;
    }

    @Override
    public void onOutTransitionAdded(
        Transition>> t,
        W w,
        WeightedPAutomaton>, W> weightedPAutomaton) {
      if (t.getLabel().equals(Field.epsilon())) return;
      importFieldTransitionsStartingAt(t, importDepth);
    }

    @Override
    public void onInTransitionAdded(
        Transition>> t,
        W w,
        WeightedPAutomaton>, W> weightedPAutomaton) {}

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = super.hashCode();
      result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (!super.equals(obj)) return false;
      if (getClass() != obj.getClass()) return false;
      ImportFieldTransitionsFrom other = (ImportFieldTransitionsFrom) obj;
      if (flowSolver == null) {
        if (other.flowSolver != null) return false;
      } else if (!flowSolver.equals(other.flowSolver)) return false;
      return true;
    }
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((baseSolver == null) ? 0 : baseSolver.hashCode());
    result = prime * result + ((flowSolver == null) ? 0 : flowSolver.hashCode());
    result = prime * result + ((curr == null) ? 0 : curr.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;
    ExecuteImportFieldStmtPOI other = (ExecuteImportFieldStmtPOI) obj;
    if (baseSolver == null) {
      if (other.baseSolver != null) return false;
    } else if (!baseSolver.equals(other.baseSolver)) return false;
    if (flowSolver == null) {
      if (other.flowSolver != null) return false;
    } else if (!flowSolver.equals(other.flowSolver)) return false;
    if (curr == null) {
      if (other.curr != null) return false;
    } else if (!curr.equals(other.curr)) return false;
    return true;
  }

  private class InsertFieldTransitionCallback {
    private final Transition>> trans;

    public InsertFieldTransitionCallback(Transition>> trans) {
      this.trans = trans;
    }

    public void trigger() {
      flowSolver.getFieldAutomaton().addTransition(trans);
      addReachable(trans.getStart());
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      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 (trans == null) {
        if (other.trans != null) return false;
      } else if (!trans.equals(other.trans)) return false;
      return true;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy