Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
qilin.pta.toolkits.turner.AbstractMVFG 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.turner;
import java.util.*;
import qilin.core.PTA;
import qilin.core.PointsToAnalysis;
import qilin.core.builder.MethodNodeFactory;
import qilin.core.builder.callgraph.Edge;
import qilin.core.builder.callgraph.OnFlyCallGraph;
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.JAssignStmt;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.model.SootMethod;
import sootup.core.types.ReferenceType;
public abstract class AbstractMVFG {
public static Map method2VFG = new HashMap<>();
protected final PTA prePTA;
protected final OCG hg;
protected final SootMethod method;
protected final Set sparkNodes = new HashSet<>();
protected final Set csNodes = new HashSet<>();
protected final Map> outEdges = new HashMap<>();
protected final Map> inEdges = new HashMap<>();
protected int total_edge_count = 0;
public static AbstractMVFG findMethodVFG(SootMethod method) {
return method2VFG.getOrDefault(method, null);
}
public AbstractMVFG(PTA prePTA, OCG hg, SootMethod method) {
this.prePTA = prePTA;
this.hg = hg;
this.method = method;
}
public Collection getAllNodes() {
return sparkNodes;
}
public int getTotalNodeCount() {
return sparkNodes.size();
}
public int getTotalEdgeCount() {
return total_edge_count;
}
public Collection getCSNodes() {
return csNodes;
}
protected void addNormalEdge(TranEdge edge) {
sparkNodes.add(edge.getSource());
sparkNodes.add(edge.getTarget());
total_edge_count++;
outEdges.computeIfAbsent(edge.getSource(), k -> new HashSet<>()).add(edge);
inEdges.computeIfAbsent(edge.getTarget(), k -> new HashSet<>()).add(edge);
}
protected void addNewEdge(AllocNode from, LocalVarNode to) {
TranEdge newEdge = new TranEdge(from, to, DFA.TranCond.NEW);
addNormalEdge(newEdge);
TranEdge newInvEdge = new TranEdge(to, from, DFA.TranCond.INEW);
addNormalEdge(newInvEdge);
}
protected void addCSLikelyEdge(AllocNode heap) {
TranEdge csLikelyEdge = new TranEdge(heap, heap, DFA.TranCond.CSLIKELY);
addNormalEdge(csLikelyEdge);
}
protected void addAssignEdge(LocalVarNode from, LocalVarNode to) {
TranEdge assignEdge = new TranEdge(from, to, DFA.TranCond.ASSIGN);
addNormalEdge(assignEdge);
TranEdge assignInvEdge = new TranEdge(to, from, DFA.TranCond.IASSIGN);
addNormalEdge(assignInvEdge);
}
protected void addStoreEdge(LocalVarNode from, LocalVarNode base) {
TranEdge storeEdge = new TranEdge(from, base, DFA.TranCond.STORE);
addNormalEdge(storeEdge);
TranEdge storeInvEdge = new TranEdge(base, from, DFA.TranCond.ISTORE);
addNormalEdge(storeInvEdge);
}
protected void addLoadEdge(LocalVarNode base, LocalVarNode to) {
TranEdge loadEdge = new TranEdge(base, to, DFA.TranCond.LOAD);
addNormalEdge(loadEdge);
TranEdge loadInvEdge = new TranEdge(to, base, DFA.TranCond.ILOAD);
addNormalEdge(loadInvEdge);
}
protected void buildVFG() {
OnFlyCallGraph callGraph = prePTA.getCallGraph();
PAG pag = prePTA.getPag();
MethodPAG srcmpag = pag.getMethodPAG(method);
MethodNodeFactory srcnf = srcmpag.nodeFactory();
LocalVarNode thisRef = (LocalVarNode) srcnf.caseThis();
QueueReader reader = srcmpag.getInternalReader().clone();
while (reader.hasNext()) {
Node from = reader.next(), to = reader.next();
if (from instanceof LocalVarNode) {
if (to instanceof LocalVarNode) this.addAssignEdge((LocalVarNode) from, (LocalVarNode) to);
else if (to instanceof FieldRefNode) {
FieldRefNode fr = (FieldRefNode) to;
this.addStoreEdge((LocalVarNode) from, (LocalVarNode) fr.getBase());
} // local-global
} else if (from instanceof AllocNode) {
if (to instanceof LocalVarNode) {
this.addNewEdge((AllocNode) from, (LocalVarNode) to);
if (hg.isCSLikely((AllocNode) from)) {
this.addCSLikelyEdge((AllocNode) from);
}
} // GlobalVarNode
} else if (from instanceof FieldRefNode) {
FieldRefNode fr = (FieldRefNode) from;
this.addLoadEdge((LocalVarNode) fr.getBase(), (LocalVarNode) to);
} // global-local
}
// add exception edges that added dynamically during the pre-analysis.
srcmpag
.getExceptionEdges()
.forEach(
(k, vs) -> {
for (Node v : vs) {
this.addAssignEdge((LocalVarNode) k, (LocalVarNode) v);
}
});
// add invoke edges
for (final Stmt s : srcmpag.getInvokeStmts()) {
AbstractInvokeExpr ie = s.getInvokeExpr();
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;
}
LocalVarNode retDest = null;
if (s instanceof JAssignStmt) {
Value dest = ((JAssignStmt) s).getLeftOp();
if (dest.getType() instanceof ReferenceType) {
retDest = pag.findLocalVarNode(method, dest, dest.getType());
}
}
LocalVarNode receiver;
if (ie instanceof AbstractInstanceInvokeExpr) {
AbstractInstanceInvokeExpr iie = (AbstractInstanceInvokeExpr) ie;
Local base = iie.getBase();
receiver = pag.findLocalVarNode(method, base, base.getType());
} else {
// static call
receiver = thisRef;
}
Set targets = new HashSet<>();
for (Iterator it = callGraph.edgesOutOf(s); it.hasNext(); ) {
Edge e = it.next();
SootMethod tgtmtd = e.tgt();
targets.add(tgtmtd);
}
if (!targets.isEmpty()) {
for (int i = 0; i < numArgs; i++) {
if (args[i] == null) continue;
ValNode argNode = pag.findValNode(args[i], method);
if (argNode instanceof LocalVarNode && satisfyAddingStoreCondition(i, targets)) {
this.addStoreEdge((LocalVarNode) argNode, receiver);
}
}
if (retDest != null && retDest.getType() instanceof ReferenceType) {
if (statisfyAddingLoadCondition(targets)) {
this.addLoadEdge(receiver, retDest);
}
}
if (statisfyAddingLoadCondition(targets)) {
LocalVarNode stmtThrowNode = srcnf.makeInvokeStmtThrowVarNode(s, method);
this.addLoadEdge(receiver, stmtThrowNode);
}
if (satisfyAddingStoreCondition(PointsToAnalysis.THIS_NODE, targets)) {
this.addStoreEdge(receiver, receiver);
}
}
}
// add param and return edges
addNormalEdge(new TranEdge(thisRef, thisRef, DFA.TranCond.PARAM));
addNormalEdge(new TranEdge(thisRef, thisRef, DFA.TranCond.IPARAM));
int numParms = method.getParameterCount();
for (int i = 0; i < numParms; i++) {
if (method.getParameterType(i) instanceof ReferenceType) {
LocalVarNode param = (LocalVarNode) srcnf.caseParm(i);
addNormalEdge(new TranEdge(param, param, DFA.TranCond.PARAM));
addNormalEdge(new TranEdge(param, param, DFA.TranCond.IPARAM));
}
}
if (method.getReturnType() instanceof ReferenceType) {
LocalVarNode mret = (LocalVarNode) srcnf.caseRet();
addStoreEdge(mret, thisRef);
}
LocalVarNode mThrow =
pag.findLocalVarNode(
method,
new Parm(method, PointsToAnalysis.THROW_NODE),
PTAUtils.getClassType("java.lang.Exception"));
if (mThrow != null) {
addStoreEdge(mThrow, thisRef);
}
}
protected abstract boolean statisfyAddingLoadCondition(Set targets);
protected abstract boolean satisfyAddingStoreCondition(int paramIndex, Set targets);
/*
* Algorithm1: x \in R(flow) \cap R(iflow).
* more efficient.
* */
public void computeNodesInPrecisionLossPatterns() {
Queue> workList = new UniqueQueue<>();
Map> state2nodes = new HashMap<>();
MethodPAG srcmpag = prePTA.getPag().getMethodPAG(method);
MethodNodeFactory srcnf = srcmpag.nodeFactory();
// initialize worklist
int numParms = method.getParameterCount();
LocalVarNode thisRef = (LocalVarNode) srcnf.caseThis();
Set startState = state2nodes.computeIfAbsent(DFA.State.S, k -> new HashSet<>());
startState.add(thisRef);
workList.add(new Pair<>(thisRef, DFA.State.S));
for (int i = 0; i < numParms; i++) {
if (method.getParameterType(i) instanceof ReferenceType) {
LocalVarNode param = (LocalVarNode) srcnf.caseParm(i);
startState.add(param);
workList.add(new Pair<>(param, DFA.State.S));
}
}
if (method.getReturnType() instanceof ReferenceType) {
LocalVarNode mret = (LocalVarNode) srcnf.caseRet();
startState.add(mret);
workList.add(new Pair<>(mret, DFA.State.S));
}
LocalVarNode mThrow = (LocalVarNode) srcnf.caseMethodThrow();
startState.add(mThrow);
workList.add(new Pair<>(mThrow, DFA.State.S));
// propagate
while (!workList.isEmpty()) {
Pair pair = workList.poll();
Object currNode = pair.getFirst();
DFA.State currState = pair.getSecond();
for (TranEdge e : outEdges.getOrDefault(currNode, Collections.emptySet())) {
Object target = e.getTarget();
DFA.TranCond tranCond = e.getTranCond();
DFA.State nextState = DFA.nextState(currState, tranCond);
if (nextState != DFA.State.ERROR) {
Set stateNodes = state2nodes.computeIfAbsent(nextState, k -> new HashSet<>());
if (stateNodes.add(target)) {
workList.add(new Pair<>(target, nextState));
}
}
}
}
// collect cs nodes.
Set flowNodes = state2nodes.getOrDefault(DFA.State.FLOW, Collections.emptySet());
Set iflowNodes = state2nodes.getOrDefault(DFA.State.IFLOW, Collections.emptySet());
for (Object sparkNode : sparkNodes) {
if (flowNodes.contains(sparkNode) && iflowNodes.contains(sparkNode)) {
csNodes.add(sparkNode);
}
}
}
}