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

qilin.pta.toolkits.common.OAG Maven / Gradle / Ivy

/* Qilin - a Java Pointer Analysis Framework
 * Copyright (C) 2021-2030 Qilin developers
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3.0 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 */

package qilin.pta.toolkits.common;

import java.util.*;
import qilin.core.PTA;
import qilin.core.builder.MethodNodeFactory;
import qilin.core.pag.AllocNode;
import qilin.core.pag.LocalVarNode;
import qilin.core.pag.MethodPAG;
import qilin.core.sets.PointsToSet;
import qilin.util.PTAUtils;
import qilin.util.graph.DirectedGraph;
import qilin.util.queue.QueueReader;
import sootup.core.model.SootMethod;

/** Implementation of Object Allocation Graph (OAG). */
public class OAG implements DirectedGraph {
  protected final PTA pta;
  protected final Map> successors;
  protected final Map> predecessors;
  protected final Set nodes = new HashSet<>();
  protected Collection rootNodes;
  protected Collection tailNodes;

  public OAG(PTA prePta) {
    this.pta = prePta;
    this.predecessors = new HashMap<>();
    this.successors = new HashMap<>();
  }

  public void build() {
    buildOAG();
    rootNodes = computeRootNodes();
    tailNodes = computeTailNodes();
  }

  @Override
  public Collection allNodes() {
    return nodes;
  }

  @Override
  public Collection predsOf(AllocNode p) {
    return getPredsOf(p);
  }

  @Override
  public Collection succsOf(AllocNode p) {
    return getSuccsOf(p);
  }

  public Collection rootNodes() {
    return rootNodes;
  }

  public Collection tailNodes() {
    return tailNodes;
  }

  public Set getPredsOf(AllocNode n) {
    return predecessors.getOrDefault(n, Collections.emptySet());
  }

  public Set getSuccsOf(AllocNode n) {
    return successors.getOrDefault(n, Collections.emptySet());
  }

  public int getInDegreeOf(AllocNode n) {
    return getPredsOf(n).size();
  }

  /**
   * @param source
   * @param dest
   * @return whether there is a path from source to target in the OAG
   */
  Map> reachableMap = new HashMap<>();

  public boolean reaches(AllocNode source, AllocNode dest) {
    Collection reachableNodes = reachableMap.get(source);
    if (reachableNodes == null) {
      reachableNodes = computeReachableNodes(source);
      reachableMap.put(source, reachableNodes);
    }
    return reachableNodes.contains(dest);
  }

  protected void buildOAG() {
    Map> pts = PTAUtils.calcStaticThisPTS(this.pta);
    for (SootMethod method : this.pta.getNakedReachableMethods()) {
      if (!PTAUtils.hasBody(method)) {
        continue;
      }
      MethodPAG srcmpag = pta.getPag().getMethodPAG(method);
      MethodNodeFactory srcnf = srcmpag.nodeFactory();
      LocalVarNode thisRef = (LocalVarNode) srcnf.caseThis();
      QueueReader reader = srcmpag.getInternalReader().clone();
      while (reader.hasNext()) {
        qilin.core.pag.Node from = reader.next(), to = reader.next();
        if (from instanceof AllocNode) {
          AllocNode tgt = (AllocNode) from;
          if (PTAUtils.isFakeMainMethod(method)) {
            // special treatment for fake main
            AllocNode src = pta.getRootNode();
            addEdge(src, tgt);
          } else if (method.isStatic()) {
            pts.getOrDefault(thisRef, Collections.emptySet())
                .forEach(
                    src -> {
                      addEdge(src, tgt);
                    });
          } else {
            PointsToSet thisPts = pta.reachingObjects(thisRef).toCIPointsToSet();
            for (Iterator it = thisPts.iterator(); it.hasNext(); ) {
              AllocNode src = it.next();
              addEdge(src, tgt);
            }
          }
        }
      }
    }
  }

  /** Add a directed object allocation edge to the OAG. */
  protected void addEdge(AllocNode src, AllocNode tgt) {
    nodes.add(src);
    nodes.add(tgt);
    this.predecessors.computeIfAbsent(tgt, k -> new HashSet<>()).add(src);
    this.successors.computeIfAbsent(src, k -> new HashSet<>()).add(tgt);
  }

  public int nodeSize() {
    return this.nodes.size();
  }

  public int edgeSize() {
    int ret = 0;
    for (AllocNode obj : predecessors.keySet()) {
      ret += predecessors.get(obj).size();
    }
    return ret;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy