use of soot.jimple.ThrowStmt in project soot by Sable.
the class ThrowInstruction method jimplify.
@Override
public void jimplify(DexBody body) {
Instruction11x throwInstruction = (Instruction11x) instruction;
ThrowStmt throwStmt = Jimple.v().newThrowStmt(body.getRegisterLocal(throwInstruction.getRegisterA()));
setUnit(throwStmt);
addTags(throwStmt);
body.add(throwStmt);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().setType(throwStmt.getOpBox(), RefType.v("java.lang.Throwable"), true);
}
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class DexNullTransformer method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
AbstractStmtSwitch checkDef = new // Alex: should also end as
AbstractStmtSwitch() {
// soon as detected as not
// used as an object
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value r = stmt.getRightOp();
if (r instanceof FieldRef) {
usedAsObject = isObject(((FieldRef) r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getType() instanceof UnknownType) {
// isObject
usedAsObject = stmt.hasTag("ObjectOpTag");
// (findArrayType
// (g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(ar.getType());
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr || r instanceof NewArrayExpr) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = isObject(((InvokeExpr) r).getType());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = false;
doBreak = true;
return;
// introduces alias
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l) {
usedAsObject = isObject(stmt.getRightOp().getType());
doBreak = true;
return;
}
}
};
AbstractStmtSwitch checkUse = new AbstractStmtSwitch() {
private boolean examineInvokeExpr(InvokeExpr e) {
List<Value> args = e.getArgs();
List<Type> argTypes = e.getMethodRef().parameterTypes();
assert args.size() == argTypes.size();
for (int i = 0; i < args.size(); i++) {
if (args.get(i) == l && isObject(argTypes.get(i))) {
return true;
}
}
// check for base
SootMethodRef sm = e.getMethodRef();
if (!sm.isStatic()) {
if (e instanceof AbstractInvokeExpr) {
AbstractInstanceInvokeExpr aiiexpr = (AbstractInstanceInvokeExpr) e;
Value b = aiiexpr.getBase();
if (b == l) {
return true;
}
}
}
return false;
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr e = stmt.getInvokeExpr();
usedAsObject = examineInvokeExpr(e);
doBreak = true;
return;
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value left = stmt.getLeftOp();
Value r = stmt.getRightOp();
if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
if (ar.getIndex() == l) {
doBreak = true;
return;
} else if (ar.getBase() == l) {
usedAsObject = true;
doBreak = true;
return;
}
}
if (left instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) left;
if (ifr.getBase() == l) {
usedAsObject = true;
doBreak = true;
return;
}
}
// used to assign
if (stmt.getRightOp() == l) {
Value l = stmt.getLeftOp();
if (l instanceof StaticFieldRef && isObject(((StaticFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
doBreak = true;
return;
} else if (l instanceof InstanceFieldRef && isObject(((InstanceFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
doBreak = true;
return;
} else if (l instanceof ArrayRef) {
Type aType = ((ArrayRef) l).getType();
if (aType instanceof UnknownType) {
usedAsObject = stmt.hasTag(// isObject(
"ObjectOpTag");
// findArrayType(g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(aType);
}
doBreak = true;
return;
}
}
// is used as value (does not exclude assignment)
if (r instanceof FieldRef) {
// isObject(((FieldRef)
usedAsObject = true;
// r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getBase() == l) {
usedAsObject = true;
} else {
// used as index
usedAsObject = false;
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr) {
throw new RuntimeException("NOT POSSIBLE StringConstant or NewExpr at " + stmt);
} else if (r instanceof NewArrayExpr) {
usedAsObject = false;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = examineInvokeExpr((InvokeExpr) stmt.getRightOp());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsObject = false;
doBreak = true;
return;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l)
throw new RuntimeException("IMPOSSIBLE 0");
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
usedAsObject = stmt.getOp() == l && isObject(body.getMethod().getReturnType());
doBreak = true;
return;
}
@Override
public void caseThrowStmt(ThrowStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
};
for (Local loc : getNullCandidates(body)) {
usedAsObject = false;
Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
// process normally
doBreak = false;
for (Unit u : defs) {
// put correct local in l
if (u instanceof DefinitionStmt) {
l = (Local) ((DefinitionStmt) u).getLeftOp();
} else if (u instanceof IfStmt) {
throw new RuntimeException("ERROR: def can not be something else than Assign or Identity statement! (def: " + u + " class: " + u.getClass() + "");
}
// check defs
u.apply(checkDef);
if (doBreak)
break;
// check uses
for (Unit use : localDefs.getUsesOf(l)) {
use.apply(checkUse);
if (doBreak)
break;
}
// for uses
if (doBreak)
break;
}
// change values
if (usedAsObject) {
for (Unit u : defs) {
replaceWithNull(u);
Set<Value> defLocals = new HashSet<Value>();
for (ValueBox vb : u.getDefBoxes()) defLocals.add(vb.getValue());
Local l = (Local) ((DefinitionStmt) u).getLeftOp();
for (Unit uuse : localDefs.getUsesOf(l)) {
Stmt use = (Stmt) uuse;
// If we have a[x] = 0 and a is an object, we may not conclude 0 -> null
if (!use.containsArrayRef() || !defLocals.contains(use.getArrayRef().getBase()))
replaceWithNull(use);
}
}
}
// end if
}
// Check for inlined zero values
AbstractStmtSwitch inlinedZeroValues = new AbstractStmtSwitch() {
final NullConstant nullConstant = NullConstant.v();
@Override
public void caseAssignStmt(AssignStmt stmt) {
// Case a = 0 with a being an object
if (isObject(stmt.getLeftOp().getType()) && isConstZero(stmt.getRightOp())) {
stmt.setRightOp(nullConstant);
return;
}
// Case a = (Object) 0
if (stmt.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) stmt.getRightOp();
if (isObject(ce.getCastType()) && isConstZero(ce.getOp())) {
stmt.setRightOp(nullConstant);
}
}
// Case a[0] = 0
if (stmt.getLeftOp() instanceof ArrayRef && isConstZero(stmt.getRightOp())) {
ArrayRef ar = (ArrayRef) stmt.getLeftOp();
if (isObjectArray(ar.getBase(), body) || stmt.hasTag("ObjectOpTag")) {
stmt.setRightOp(nullConstant);
}
}
}
private boolean isConstZero(Value rightOp) {
if (rightOp instanceof IntConstant && ((IntConstant) rightOp).value == 0)
return true;
if (rightOp instanceof LongConstant && ((LongConstant) rightOp).value == 0)
return true;
return false;
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
if (stmt.getOp() instanceof IntConstant && isObject(body.getMethod().getReturnType())) {
IntConstant iconst = (IntConstant) stmt.getOp();
assert iconst.value == 0;
stmt.setOp(nullConstant);
}
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
stmt.setOp(nullConstant);
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
stmt.setOp(nullConstant);
}
};
final NullConstant nullConstant = NullConstant.v();
for (Unit u : body.getUnits()) {
u.apply(inlinedZeroValues);
if (u instanceof Stmt) {
Stmt stmt = (Stmt) u;
if (stmt.containsInvokeExpr()) {
InvokeExpr invExpr = stmt.getInvokeExpr();
for (int i = 0; i < invExpr.getArgCount(); i++) if (isObject(invExpr.getMethodRef().parameterType(i)))
if (invExpr.getArg(i) instanceof IntConstant) {
IntConstant iconst = (IntConstant) invExpr.getArg(i);
assert iconst.value == 0;
invExpr.setArg(i, nullConstant);
}
}
}
}
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class IFDSUninitializedVariables method createFlowFunctionsFactory.
@Override
public FlowFunctions<Unit, Local, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Local, SootMethod>() {
@Override
public FlowFunction<Local> getNormalFlowFunction(Unit curr, Unit succ) {
final SootMethod m = interproceduralCFG().getMethodOf(curr);
if (Scene.v().getEntryPoints().contains(m) && interproceduralCFG().isStartPoint(curr)) {
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(Local source) {
if (source == zeroValue()) {
Set<Local> res = new LinkedHashSet<Local>();
res.addAll(m.getActiveBody().getLocals());
for (int i = 0; i < m.getParameterCount(); i++) res.remove(m.getActiveBody().getParameterLocal(i));
return res;
}
return Collections.emptySet();
}
};
}
if (curr instanceof DefinitionStmt) {
final DefinitionStmt definition = (DefinitionStmt) curr;
final Value leftOp = definition.getLeftOp();
if (leftOp instanceof Local) {
final Local leftOpLocal = (Local) leftOp;
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
List<ValueBox> useBoxes = definition.getUseBoxes();
for (ValueBox valueBox : useBoxes) {
if (valueBox.getValue().equivTo(source)) {
LinkedHashSet<Local> res = new LinkedHashSet<Local>();
res.add(source);
res.add(leftOpLocal);
return res;
}
}
if (leftOp.equivTo(source))
return Collections.emptySet();
return Collections.singleton(source);
}
};
}
}
return Identity.v();
}
@Override
public FlowFunction<Local> getCallFlowFunction(Unit callStmt, final SootMethod destinationMethod) {
Stmt stmt = (Stmt) callStmt;
InvokeExpr invokeExpr = stmt.getInvokeExpr();
final List<Value> args = invokeExpr.getArgs();
final List<Local> localArguments = new ArrayList<Local>();
for (Value value : args) if (value instanceof Local)
localArguments.add((Local) value);
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
// Do not map parameters for <clinit> edges
if (destinationMethod.getName().equals("<clinit>") || destinationMethod.getSubSignature().equals("void run()"))
return Collections.emptySet();
for (Local localArgument : localArguments) {
if (source.equivTo(localArgument)) {
return Collections.<Local>singleton(destinationMethod.getActiveBody().getParameterLocal(args.indexOf(localArgument)));
}
}
if (source == zeroValue()) {
// gen all locals that are not parameter locals
Collection<Local> locals = destinationMethod.getActiveBody().getLocals();
LinkedHashSet<Local> uninitializedLocals = new LinkedHashSet<Local>(locals);
for (int i = 0; i < destinationMethod.getParameterCount(); i++) {
uninitializedLocals.remove(destinationMethod.getActiveBody().getParameterLocal(i));
}
return uninitializedLocals;
}
return Collections.emptySet();
}
};
}
@Override
public FlowFunction<Local> getReturnFlowFunction(final Unit callSite, SootMethod calleeMethod, final Unit exitStmt, Unit returnSite) {
if (callSite instanceof DefinitionStmt) {
final DefinitionStmt definition = (DefinitionStmt) callSite;
if (definition.getLeftOp() instanceof Local) {
final Local leftOpLocal = (Local) definition.getLeftOp();
if (exitStmt instanceof ReturnStmt) {
final ReturnStmt returnStmt = (ReturnStmt) exitStmt;
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(Local source) {
if (returnStmt.getOp().equivTo(source))
return Collections.singleton(leftOpLocal);
return Collections.emptySet();
}
};
} else if (exitStmt instanceof ThrowStmt) {
// if we throw an exception, LHS of call is undefined
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
if (source == zeroValue())
return Collections.singleton(leftOpLocal);
else
return Collections.emptySet();
}
};
}
}
}
return KillAll.v();
}
@Override
public FlowFunction<Local> getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
if (callSite instanceof DefinitionStmt) {
DefinitionStmt definition = (DefinitionStmt) callSite;
if (definition.getLeftOp() instanceof Local) {
final Local leftOpLocal = (Local) definition.getLeftOp();
return new Kill<Local>(leftOpLocal);
}
}
return Identity.v();
}
};
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class ExceptionChecker method internalTransform.
@Override
protected void internalTransform(Body b, String phaseName, Map options) {
Iterator it = b.getUnits().iterator();
while (it.hasNext()) {
Stmt s = (Stmt) it.next();
if (s instanceof ThrowStmt) {
ThrowStmt ts = (ThrowStmt) s;
checkThrow(b, ts);
} else if (s instanceof InvokeStmt) {
InvokeStmt is = (InvokeStmt) s;
checkInvoke(b, is);
} else if ((s instanceof AssignStmt) && (((AssignStmt) s).getRightOp() instanceof InvokeExpr)) {
InvokeExpr ie = (InvokeExpr) ((AssignStmt) s).getRightOp();
checkInvokeExpr(b, ie, s);
}
}
}
use of soot.jimple.ThrowStmt in project soot by Sable.
the class ExceptionalUnitGraph method buildExceptionalEdges.
/**
* Method to compute the edges corresponding to exceptional control flow.
*
* @param throwAnalysis
* the source of information about the exceptions which each
* {@link Unit} may throw.
*
* @param unitToExceptionDests
* A <code>Map</code> from {@link Unit}s to {@link Collection}s
* of {@link ExceptionalUnitGraph.ExceptionDest ExceptionDest}s
* which represent the handlers that might catch exceptions
* thrown by the <code>Unit</code>. This is an ``in parameter''.
*
* @param unitToSuccs
* A <code>Map</code> from <code>Unit</code>s to {@link List}s of
* <code>Unit</code>s. This is an ``out parameter'';
* <code>buildExceptionalEdges</code> will add a mapping from
* every <code>Unit</code> in the body that may throw an
* exception that could be caught by a {@link Trap} in the body
* to a list of its exceptional successors.
*
* @param unitToPreds
* A <code>Map</code> from <code>Unit</code>s to
* <code>List</code>s of <code>Unit</code>s. This is an ``out
* parameter''; <code>buildExceptionalEdges</code> will add a
* mapping from each handler unit that may catch an exception to
* the list of <code>Unit</code>s whose exceptions it may catch.
* @param omitExceptingUnitEdges
* Indicates whether to omit exceptional edges from excepting
* units which lack side effects
*
* @return a {@link Set} of trap <code>Unit</code>s that might catch
* exceptions thrown by the first <code>Unit</code> in the
* {@link Body} associated with the graph being constructed. Such
* trap <code>Unit</code>s may need to be added to the list of heads
* (depending on your definition of heads), since they can be the
* first <code>Unit</code> in the <code>Body</code> which actually
* completes execution.
*/
protected Set<Unit> buildExceptionalEdges(ThrowAnalysis throwAnalysis, Map<Unit, Collection<ExceptionDest>> unitToExceptionDests, Map<Unit, List<Unit>> unitToSuccs, Map<Unit, List<Unit>> unitToPreds, boolean omitExceptingUnitEdges) {
Set<Unit> trapsThatAreHeads = new ArraySet<Unit>();
Unit entryPoint = unitChain.getFirst();
for (Entry<Unit, Collection<ExceptionDest>> entry : unitToExceptionDests.entrySet()) {
Unit thrower = entry.getKey();
List<Unit> throwersPreds = getUnexceptionalPredsOf(thrower);
Collection<ExceptionDest> dests = entry.getValue();
// We need to recognize:
// - caught exceptions for which we must add edges from the
// thrower's predecessors to the catcher:
// - all exceptions of non-throw instructions;
// - implicit exceptions of throw instructions.
//
// - caught exceptions where we must add edges from the
// thrower itself to the catcher:
// - any exception of non-throw instructions if
// omitExceptingUnitEdges is not set.
// - any exception of non-throw instructions with side effects.
// - explicit exceptions of throw instructions
// - implicit exceptions of throw instructions if
// omitExceptingUnitEdges is not set.
// - implicit exceptions of throw instructions with possible
// side effects (this is only possible for the grimp
// IR, where the throw's argument may be an
// expression---probably a NewInvokeExpr---which
// might have executed partially before the
// exception arose).
//
// Note that a throw instruction may be capable of throwing a given
// Throwable type both implicitly and explicitly.
//
// We track these situations using predThrowables and
// selfThrowables. Essentially predThrowables is the set
// of Throwable types to whose catchers there should be
// edges from predecessors of the thrower, while
// selfThrowables is the set of Throwable types to whose
// catchers there should be edges from the thrower itself,
// but we we take some short cuts to avoid calling
// ThrowableSet.catchableAs() when we can avoid it.
boolean alwaysAddSelfEdges = ((!omitExceptingUnitEdges) || mightHaveSideEffects(thrower));
ThrowableSet predThrowables = null;
ThrowableSet selfThrowables = null;
if (thrower instanceof ThrowInst) {
ThrowInst throwInst = (ThrowInst) thrower;
predThrowables = throwAnalysis.mightThrowImplicitly(throwInst);
selfThrowables = throwAnalysis.mightThrowExplicitly(throwInst);
} else if (thrower instanceof ThrowStmt) {
ThrowStmt throwStmt = (ThrowStmt) thrower;
predThrowables = throwAnalysis.mightThrowImplicitly(throwStmt);
selfThrowables = throwAnalysis.mightThrowExplicitly(throwStmt);
}
for (ExceptionDest dest : dests) {
if (dest.getTrap() != null) {
Unit catcher = dest.getTrap().getHandlerUnit();
RefType trapsType = dest.getTrap().getException().getType();
if (predThrowables == null || predThrowables.catchableAs(trapsType)) {
// catcher.
if (thrower == entryPoint) {
trapsThatAreHeads.add(catcher);
}
for (Unit pred : throwersPreds) {
addEdge(unitToSuccs, unitToPreds, pred, catcher);
}
}
if (alwaysAddSelfEdges || (selfThrowables != null && selfThrowables.catchableAs(trapsType))) {
addEdge(unitToSuccs, unitToPreds, thrower, catcher);
}
}
}
}
// worklist containing CFG edges that lead to such a handler.
class CFGEdge {
// If null, represents an edge to the handler
Unit head;
// from the fictitious "predecessor" of the
// very first unit in the chain. I.e., tail
// is a handler which might be reached as a
// result of an exception thrown by the
// first Unit in the Body.
Unit tail;
CFGEdge(Unit head, Unit tail) {
if (tail == null)
throw new RuntimeException("invalid CFGEdge(" + (head == null ? "null" : head.toString()) + ',' + "null" + ')');
this.head = head;
this.tail = tail;
}
@Override
public boolean equals(Object rhs) {
if (rhs == this) {
return true;
}
if (!(rhs instanceof CFGEdge)) {
return false;
}
CFGEdge rhsEdge = (CFGEdge) rhs;
return ((this.head == rhsEdge.head) && (this.tail == rhsEdge.tail));
}
@Override
public int hashCode() {
// Following Joshua Bloch's recipe in "Effective Java", Item 8:
int result = 17;
result = 37 * result + this.head.hashCode();
result = 37 * result + this.tail.hashCode();
return result;
}
}
LinkedList<CFGEdge> workList = new LinkedList<CFGEdge>();
for (Trap trap : body.getTraps()) {
Unit handlerStart = trap.getHandlerUnit();
if (mightThrowToIntraproceduralCatcher(handlerStart)) {
List<Unit> handlerPreds = getUnexceptionalPredsOf(handlerStart);
for (Unit pred : handlerPreds) {
workList.addLast(new CFGEdge(pred, handlerStart));
}
handlerPreds = getExceptionalPredsOf(handlerStart);
for (Unit pred : handlerPreds) {
workList.addLast(new CFGEdge(pred, handlerStart));
}
if (trapsThatAreHeads.contains(handlerStart)) {
workList.addLast(new CFGEdge(null, handlerStart));
}
}
}
// the handler's exception.
while (workList.size() > 0) {
CFGEdge edgeToThrower = workList.removeFirst();
Unit pred = edgeToThrower.head;
Unit thrower = edgeToThrower.tail;
Collection<ExceptionDest> throwerDests = getExceptionDests(thrower);
for (ExceptionDest dest : throwerDests) {
if (dest.getTrap() != null) {
Unit handlerStart = dest.getTrap().getHandlerUnit();
boolean edgeAdded = false;
if (pred == null) {
if (!trapsThatAreHeads.contains(handlerStart)) {
trapsThatAreHeads.add(handlerStart);
edgeAdded = true;
}
} else {
if (!getExceptionalSuccsOf(pred).contains(handlerStart)) {
addEdge(unitToSuccs, unitToPreds, pred, handlerStart);
edgeAdded = true;
}
}
if (edgeAdded && mightThrowToIntraproceduralCatcher(handlerStart)) {
workList.addLast(new CFGEdge(pred, handlerStart));
}
}
}
}
return trapsThatAreHeads;
}
Aggregations