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

qilin.pta.toolkits.debloaterx.IntraFlowAnalysis Maven / Gradle / Ivy

package qilin.pta.toolkits.debloaterx;

import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import qilin.core.builder.MethodNodeFactory;
import qilin.core.pag.*;
import qilin.util.PTAUtils;
import qilin.util.Pair;
import qilin.util.queue.QueueReader;
import qilin.util.queue.UniqueQueue;
import sootup.core.jimple.basic.Local;
import sootup.core.jimple.basic.Value;
import sootup.core.jimple.common.constant.NullConstant;
import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr;
import sootup.core.jimple.common.expr.AbstractInvokeExpr;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.model.SootMethod;
import sootup.core.signatures.MethodSubSignature;
import sootup.core.types.ArrayType;
import sootup.core.types.ClassType;
import sootup.core.types.ReferenceType;
import sootup.core.types.Type;

/*
 * Implementation of Algorithm 3 and Fig 10 in the paper.
 * */
public class IntraFlowAnalysis {
  private final PAG pag;
  private final XUtility utility;
  private final SootMethod method;
  protected final XPAG xpag;
  protected final Set params = new HashSet<>();

  public IntraFlowAnalysis(XUtility utility, SootMethod method) {
    this.utility = utility;
    this.pag = utility.getPta().getPag();
    this.method = method;
    this.xpag = utility.getXpag();
    collectParams();
  }

  protected void collectParams() {
    MethodPAG srcmpag = pag.getMethodPAG(method);
    MethodNodeFactory srcnf = srcmpag.nodeFactory();
    VarNode thisNode = srcnf.caseThis();
    // handle parameters
    for (int i = 0; i < method.getParameterCount(); ++i) {
      if (method.getParameterType(i) instanceof ReferenceType
          && !PTAUtils.isPrimitiveArrayType(method.getParameterType(i))) {
        LocalVarNode param = (LocalVarNode) srcnf.caseParm(i);
        this.params.add(param);
      }
    }
    this.params.add((LocalVarNode) thisNode);
  }

  //////////////////////////////////////////////////////////////////////////////////
  /*
   * x = y = z = ... = node;
   * */
  Set epsilon(Node node) {
    Queue queue = new UniqueQueue<>();
    for (Edge edge : xpag.getOutEdges(node)) {
      queue.add(edge.to);
    }
    Set visit = new HashSet<>();
    while (!queue.isEmpty()) {
      Node front = queue.poll();
      visit.add(front);
      for (Edge edge : xpag.getOutEdges(front)) {
        if (edge.kind == EdgeKind.ASSIGN && !visit.contains(edge.to)) {
          queue.add(edge.to);
        }
      }
    }
    return visit;
  }

  /*
   * t = new T;
   * x = ... = t;
   * return x;
   * */
  public boolean isDirectlyReturnedHeap(AllocNode heap) {
    Set visit = epsilon(heap);
    boolean flag = false;
    for (Node node : visit) {
      if (node instanceof LocalVarNode) {
        LocalVarNode lvn = (LocalVarNode) node;
        if (lvn.isReturn()) {
          flag = true;
        }
      }
    }
    return flag;
  }

  public boolean isContentFromParam(AllocNode heap) {
    Type heapType = heap.getType();
    if (heapType instanceof ClassType) {
      return isInstanceObjectContentFromParam(heap);
    } else {
      return isArrayContentFromParam(heap);
    }
  }

  /*
   * return true iff heap.f comes from any parameter of heap.getMethod().
   * */
  private boolean isInstanceObjectContentFromParam(AllocNode heap) {
    Set paramInArgs = collectParamInArguments(heap);
    if (paramInArgs.isEmpty()) {
      return false;
    }
    Queue queue = new UniqueQueue<>();
    Set visited = new HashSet<>();
    queue.addAll(params);
    while (!queue.isEmpty()) {
      Node front = queue.poll();
      if (paramInArgs.contains(front)) {
        return true;
      }
      visited.add(front);
      for (Edge edge : xpag.getOutEdges(front)) {
        if (edge.kind == EdgeKind.ASSIGN
            || edge.kind == EdgeKind.CLOAD
            || edge.kind == EdgeKind.LOAD) {
          if (!visited.contains(edge.to)) {
            queue.add(edge.to);
          }
        }
      }
    }
    return false;
  }

  private Set collectParamInArguments(AllocNode heap) {
    ClassType type = (ClassType) heap.getType();
    Set x = epsilon(heap);
    Set ret = new HashSet<>();
    HeapContainerQuery hcq = this.utility.getHCQ(heap);
    Set inParams = hcq.getInParamsToCSFields();
    MethodPAG srcmpag = pag.getMethodPAG(method);
    for (final Stmt s : srcmpag.getInvokeStmts()) {
      AbstractInvokeExpr ie = s.getInvokeExpr();
      if (!(ie instanceof AbstractInstanceInvokeExpr)) {
        continue;
      }
      AbstractInstanceInvokeExpr iie = (AbstractInstanceInvokeExpr) ie;
      Local base = iie.getBase();
      LocalVarNode receiver = pag.findLocalVarNode(method, base, base.getType());
      if (!x.contains(receiver)) {
        continue;
      }
      int numArgs = ie.getArgCount();
      Value[] args = new Value[numArgs];
      for (int i = 0; i < numArgs; i++) {
        Value arg = ie.getArg(i);
        if (!(arg.getType() instanceof ReferenceType) || arg instanceof NullConstant) {
          continue;
        }
        args[i] = arg;
      }
      MethodSubSignature subSig = iie.getMethodSignature().getSubSignature();
      VirtualCallSite virtualCallSite =
          new VirtualCallSite(
              receiver,
              s,
              new ContextMethod(method, utility.getPta().emptyContext()),
              iie,
              subSig,
              qilin.core.builder.callgraph.Edge.ieToKind(iie));
      QueueReader targets = pag.getCgb().dispatch(type, virtualCallSite);
      while (targets.hasNext()) {
        SootMethod target = targets.next();
        MethodPAG tgtmpag = pag.getMethodPAG(target);
        MethodNodeFactory tgtnf = tgtmpag.nodeFactory();
        int numParms = target.getParameterCount();
        if (numParms != numArgs) {
          System.out.println(target);
        }
        for (int i = 0; i < numParms; i++) {
          if (target.getParameterType(i) instanceof ReferenceType) {
            if (args[i] != null) {
              ValNode argNode = pag.findValNode(args[i], method);
              if (argNode instanceof LocalVarNode) {
                LocalVarNode lvn = (LocalVarNode) argNode;
                LocalVarNode param = (LocalVarNode) tgtnf.caseParm(i);
                if (inParams.contains(param)) {
                  ret.add(lvn);
                }
              }
            }
          }
        }
      }
    }
    return ret;
  }

  /*
   * x = new T[]
   * x[i] = param.*;
   * */
  private boolean isArrayContentFromParam(AllocNode heap) {
    if (!(heap.getType() instanceof ArrayType)) {
      return false;
    }
    Set x = epsilon(heap);
    Queue queue = new UniqueQueue<>();
    Set visited = new HashSet<>();
    queue.addAll(params);
    while (!queue.isEmpty()) {
      Node front = queue.poll();
      visited.add(front);
      for (Edge edge : xpag.getOutEdges(front)) {
        if (edge.kind == EdgeKind.ASSIGN
            || edge.kind == EdgeKind.CLOAD
            || edge.kind == EdgeKind.LOAD) {
          if (!visited.contains(edge.to)) {
            queue.add(edge.to);
          }
        }
        if (edge.kind == EdgeKind.STORE) {
          if (x.contains(edge.to)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  private State nextState(State currState, EdgeKind kind) {
    switch (currState) {
      case O:
        {
          if (kind == EdgeKind.NEW) {
            return State.VPlus;
          }
        }
      case VPlus:
        {
          if (kind == EdgeKind.ASSIGN) {
            return State.VPlus;
          } else if (kind == EdgeKind.STORE) {
            return State.VMinus;
          }
        }
      case VMinus:
        {
          if (kind == EdgeKind.IASSIGN) {
            return State.VMinus;
          } else if (kind == EdgeKind.ILOAD) {
            return State.VMinus;
          } else if (kind == EdgeKind.INEW) {
            return State.O;
          }
        }
    }
    return State.Error;
  }

  /*
   * implementation of nextNodeStates in Algorithm 3 in the paper. It also encodes Fig 10 in the paper.
   * */
  private Set> getNextNodeStates(
      Pair nodeState, Set thisAlias, Set stFields) {
    Node node = nodeState.getFirst();
    State state = nodeState.getSecond();
    Set> ret = new HashSet<>();
    for (Edge edge : xpag.getOutEdges(node)) {
      State nextState = nextState(state, edge.kind);
      if (nextState != State.Error) {
        if (edge.kind == EdgeKind.STORE && thisAlias.contains(edge.to)) {
          Type type = edge.field.getType();
          if (!utility.isCoarseType(type)) {
            continue;
          }
          stFields.add(edge.field);
        } else if (edge.kind == EdgeKind.ILOAD && thisAlias.contains(edge.to)) {
          Type type = edge.field.getType();
          if (!utility.isCoarseType(type)) {
            continue;
          }
          stFields.add(edge.field);
        } else {
          ret.add(new Pair<>(edge.to, nextState));
        }
      }
    }
    return ret;
  }

  /*
   * Implementation of Algorithm 3 in the paper.
   * */
  public Set retrieveStoreFields(AllocNode heap) {
    Set ret = new HashSet<>();
    MethodPAG srcmpag = pag.getMethodPAG(method);
    MethodNodeFactory srcnf = srcmpag.nodeFactory();
    VarNode thisNode = srcnf.caseThis();
    Set thisAlias = epsilon(thisNode);
    Queue> queue = new UniqueQueue<>();
    Set> visited = new HashSet<>();
    queue.add(new Pair<>(heap, State.O));
    while (!queue.isEmpty()) {
      Pair front = queue.poll();
      visited.add(front);
      Set> nextStates = getNextNodeStates(front, thisAlias, ret);
      for (Pair nextState : nextStates) {
        if (!visited.contains(nextState)) {
          queue.add(nextState);
        }
      }
    }
    return ret;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy