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

qilin.core.pag.MethodPAG 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.core.pag;

import java.util.*;
import qilin.CoreConfig;
import qilin.core.PTAScene;
import qilin.core.builder.MethodNodeFactory;
import qilin.util.DataFactory;
import qilin.util.PTAUtils;
import qilin.util.queue.ChunkedQueue;
import qilin.util.queue.QueueReader;
import sootup.core.jimple.Jimple;
import sootup.core.jimple.basic.Trap;
import sootup.core.jimple.common.ref.JStaticFieldRef;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.model.Body;
import sootup.core.model.SootClass;
import sootup.core.model.SootField;
import sootup.core.model.SootMethod;

/**
 * Part of a pointer assignment graph for a single method.
 *
 * @author Ondrej Lhotak
 */
public class MethodPAG {
  private final ChunkedQueue internalEdges = new ChunkedQueue<>();
  private final QueueReader internalReader = internalEdges.reader();
  private final Set clinits = DataFactory.createSet();
  private final Collection invokeStmts = DataFactory.createSet();
  public Body body;

  /**
   * Since now the exception analysis is handled on-the-fly, we should record the exception edges
   * explicitly for Eagle and Turner.
   */
  private final Map> exceptionEdges = DataFactory.createMap();

  protected MethodNodeFactory nodeFactory;
  protected final PTAScene ptaScene;
  SootMethod method;
  /*
   * List[i-1] is wrappered in List[i].
   * We have to extend the following structure from Map> to
   * Map>> because there exists cases where the same
   * node are thrown more than once and lies in different catch blocks.
   * */
  public final Map> stmt2wrapperedTraps = DataFactory.createMap();
  public final Map>> node2wrapperedTraps = DataFactory.createMap();

  public MethodPAG(PAG pag, SootMethod m, Body body) {
    this.ptaScene = pag.getPta().getScene();
    this.method = m;
    this.nodeFactory = new MethodNodeFactory(pag, this);
    this.body = body;
    build();
  }

  public SootMethod getMethod() {
    return method;
  }

  public MethodNodeFactory nodeFactory() {
    return nodeFactory;
  }

  public Collection getInvokeStmts() {
    return invokeStmts;
  }

  public boolean addCallStmt(Stmt unit) {
    return this.invokeStmts.add(unit);
  }

  protected void build() {
    // this method is invalid but exists in pmd-deps.jar
    if (method
        .getSignature()
        .toString()
        .equals(
            "")) {
      return;
    }
    buildException();
    buildNormal();
    addMiscEdges();
  }

  protected void buildNormal() {
    if (method.isStatic()) {
      if (!PTAUtils.isFakeMainMethod(method)) {
        SootClass sc = ptaScene.getView().getClass(method.getDeclaringClassType()).get();
        nodeFactory.clinitsOf(sc).forEach(this::addTriggeredClinit);
      }
    }
    for (Stmt unit : body.getStmts()) {
      try {
        nodeFactory.handleStmt(unit);
      } catch (Exception e) {
        System.out.println("Warning:" + e + " in " + this.getClass());
      }
    }
  }

  protected void buildException() {
    // we use the same logic as doop (library/exceptions/precise.logic).
    if (!CoreConfig.v().getPtaConfig().preciseExceptions) {
      return;
    }
    // List traps = body.getTraps();
    // //    List units = body.getStmts();
    // Set inTraps = DataFactory.createSet();
  }

  private void addStmtTrap(Node src, Stmt stmt, Trap trap) {
    Map> stmt2Traps =
        node2wrapperedTraps.computeIfAbsent(src, k -> DataFactory.createMap());
    List trapList = stmt2Traps.computeIfAbsent(stmt, k -> DataFactory.createList());
    trapList.add(trap);
    stmt2wrapperedTraps.computeIfAbsent(stmt, k -> DataFactory.createList()).add(trap);
  }

  protected void addMiscEdges() {
    if (method
        .getSignature()
        .toString()
        .equals(
            "(java.lang.Object,java.lang.ref.ReferenceQueue)>")) {
      // Implements the special status of java.lang.ref.Reference just as in Doop
      // (library/reference.logic).
      SootClass sootClass = ptaScene.getSootClass("java.lang.ref.Reference");
      SootField sf = sootClass.getField("pending").get();
      JStaticFieldRef sfr = Jimple.newStaticFieldRef(sf.getSignature());
      addInternalEdge(nodeFactory.caseThis(), nodeFactory.getNode(sfr));
    }
  }

  public void addInternalEdge(Node src, Node dst) {
    if (src == null) {
      return;
    }
    internalEdges.add(src);
    internalEdges.add(dst);
  }

  public QueueReader getInternalReader() {
    return internalReader;
  }

  public void addTriggeredClinit(SootMethod clinit) {
    clinits.add(clinit);
  }

  public Iterator triggeredClinits() {
    return clinits.iterator();
  }

  public void addExceptionEdge(Node from, Node to) {
    this.exceptionEdges.computeIfAbsent(from, k -> DataFactory.createSet()).add(to);
  }

  public Map> getExceptionEdges() {
    return this.exceptionEdges;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy