/*
* Copyright (C) 2015 The Pennsylvania State University and the University of Wisconsin
* Systems and Internet Infrastructure Security Laboratory
*
* Author: Damien Octeau
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.psu.cse.siis.ic3;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import soot.MethodOrMethodContext;
import soot.Scene;
import soot.SootMethod;
import soot.Unit;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.toolkits.callgraph.ReachableMethods;
import soot.toolkits.graph.ExceptionalUnitGraph;
import edu.psu.cse.siis.coal.AnalysisParameters;
import edu.psu.cse.siis.coal.Model;
import edu.psu.cse.siis.coal.PropagationSolver;
import edu.psu.cse.siis.coal.PropagationTimers;
import edu.psu.cse.siis.coal.Result;
import edu.psu.cse.siis.coal.ResultBuilder;
import edu.psu.cse.siis.coal.arguments.Argument;
import edu.psu.cse.siis.coal.arguments.ArgumentValueManager;
import edu.psu.cse.siis.coal.values.BasePropagationValue;
import edu.psu.cse.siis.coal.values.PropagationValue;
public class Ic3ResultBuilder implements ResultBuilder {
private Map<SootMethod, Set<String>> entryPointMap;
public void setEntryPointMap(Map<SootMethod, Set<String>> entryPointMap) {
this.entryPointMap = entryPointMap;
}
@Override
public Result buildResult(PropagationSolver solver) {
PropagationTimers.v().resultGeneration.start();
Result result = new Ic3Result(entryPointMap);
List<MethodOrMethodContext> eps =
new ArrayList<MethodOrMethodContext>(Scene.v().getEntryPoints());
ReachableMethods reachableMethods =
new ReachableMethods(Scene.v().getCallGraph(), eps.iterator(), null);
reachableMethods.update();
long reachableStatements = 0;
for (Iterator<MethodOrMethodContext> iter = reachableMethods.listener(); iter.hasNext();) {
SootMethod method = iter.next().method();
if (method.hasActiveBody()
&& !Model.v().isExcludedClass(method.getDeclaringClass().getName())
&& !method.getDeclaringClass().getName().equals("dummyMainClass")
&& !method.getDeclaringClass().getName().startsWith("android.support")
&& !method.getDeclaringClass().getName().startsWith("android.provider")) {
++PropagationTimers.v().reachableMethods;
ExceptionalUnitGraph cfg = new ExceptionalUnitGraph(method.getActiveBody());
Stack<Unit> stack = new Stack<>();
for (Unit unit : cfg.getHeads()) {
stack.push(unit);
}
Set<Unit> visited = new HashSet<>();
while (!stack.empty()) {
Unit unit = stack.pop();
if (visited.contains(unit)) {
continue;
} else {
visited.add(unit);
}
for (Unit successor : cfg.getSuccsOf(unit)) {
stack.push(successor);
}
Argument[] arguments = Model.v().getArgumentsForQuery((Stmt) unit);
if (arguments != null) {
boolean foundModeledType = false;
for (Argument argument : arguments) {
if (Model.v().isModeledType(argument.getType())) {
foundModeledType = true;
break;
}
}
Stmt stmt = (Stmt) unit;
for (Argument argument : arguments) {
if (Model.v().isModeledType(argument.getType())) {
int argnum = argument.getArgnum()[0];
BasePropagationValue basePropagationValue;
InvokeExpr invokeExpr = stmt.getInvokeExpr();
if (argnum >= 0) {
basePropagationValue = solver.resultAt(unit, invokeExpr.getArg(argnum));
} else if (invokeExpr instanceof InstanceInvokeExpr && argnum == -1) {
InstanceInvokeExpr instanceInvokeExpr = (InstanceInvokeExpr) invokeExpr;
basePropagationValue = solver.resultAt(stmt, instanceInvokeExpr.getBase());
} else {
throw new RuntimeException("Unexpected argument number " + argnum
+ " for invoke expression " + invokeExpr);
}
if (basePropagationValue instanceof PropagationValue) {
PropagationValue propagationValue = (PropagationValue) basePropagationValue;
PropagationTimers.v().resultGeneration.end();
PropagationTimers.v().valueComposition.start();
propagationValue.makeFinalValue(solver);
PropagationTimers.v().valueComposition.end();
PropagationTimers.v().resultGeneration.start();
result.addResult(unit, argument.getArgnum()[0], propagationValue);
} else {
result.addResult(unit, argument.getArgnum()[0], basePropagationValue);
}
} else if (foundModeledType || AnalysisParameters.v().inferNonModeledTypes()) {
// We infer non-modeled types if one of the arguments of the query is a modeled type
// or if the analysis settings tell us to do so.
result.addResult(unit, argument.getArgnum()[0], ArgumentValueManager.v()
.getArgumentValues(argument, unit));
}
}
}
}
reachableStatements += visited.size();
}
PropagationTimers.v().reachableStatements += reachableStatements;
}
PropagationTimers.v().resultGeneration.end();
return result;
}
}