@Override protected void internalTransform(Body b, String phaseName, Map<String, String> options) { LocalCreation lc = new LocalCreation(b.getLocals(), "ex"); for (Iterator<Unit> unitIt = b.getUnits().snapshotIterator(); unitIt.hasNext(); ) { Unit u = unitIt.next(); // Check for a null exception if (u instanceof ThrowStmt) { ThrowStmt throwStmt = (ThrowStmt) u; if (throwStmt.getOp() == NullConstant.v() || throwStmt.getOp().equals(IntConstant.v(0)) || throwStmt.getOp().equals(LongConstant.v(0))) { createThrowStmt(b, throwStmt, lc); } } } }
@Override public KillGenInfo propagateNormalFlow(Trackable trackable, Unit curr, Unit succ) { if (curr instanceof ReturnStmt) { Value retValue = getBase(((ReturnStmt) curr).getOp()); if (retValue instanceof Constant) { return kill(); } else { ReturnValueTaint retValTaint = (ReturnValueTaint) trackable; if (AnalysisUtil.isAssignable(retValTaint.type, retValue.getType())) return propagate(new Taint(curr, trackable, retValue, retValTaint.type)); else return kill(); } } else if (curr instanceof ThrowStmt) return kill(); throw new IllegalStateException(); }
/** * Checks whether the given method is a library stub method * @param method The method to check * @return True if the given method is an Android library stub, false * otherwise */ private boolean methodIsAndroidStub(SootMethod method) { if (!(Options.v().src_prec() == Options.src_prec_apk && method.getDeclaringClass().isLibraryClass() && SystemClassHandler.isClassInSystemPackage( method.getDeclaringClass().getName()))) return false; // Check whether there is only a single throw statement for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof DefinitionStmt) { DefinitionStmt defStmt = (DefinitionStmt) u; if (!(defStmt.getRightOp() instanceof ThisRef) && !(defStmt.getRightOp() instanceof ParameterRef) && !(defStmt.getRightOp() instanceof NewExpr)) return false; } else if (u instanceof InvokeStmt) { InvokeStmt stmt = (InvokeStmt) u; // Check for exception constructor invocations SootMethod callee = stmt.getInvokeExpr().getMethod(); if (!callee.getSubSignature().equals("void <init>(java.lang.String)")) // Check for super class constructor invocation if (!(method.getDeclaringClass().hasSuperclass() && callee.getDeclaringClass() == method.getDeclaringClass().getSuperclass() && callee.getName().equals("<init>"))) return false; } else if (!(u instanceof ThrowStmt)) return false; } return true; }
public void caseThrowStmt(ThrowStmt stmt) { if (uses) { if (stmt.getOp() instanceof Local) { TypeVariable op = resolver.typeVariable((Local) stmt.getOp()); op.addParent(resolver.typeVariable(RefType.v("java.lang.Throwable"))); } } }
@Override public void caseThrowStmt(ThrowStmt stmt) { Value exception = stmt.getOp(); constantV.setOrigStmt(stmt); Register exceptionReg = regAlloc.asImmediate(exception, constantV); addInsn(new Insn11x(Opcode.THROW, exceptionReg), stmt); }
/** * Utility method, to be called only after the unitToPreds and unitToSuccs * maps have been built. It defines the graph's set of heads to include the * first {@link Unit} in the graph's body, together with all the * <code>Unit</code>s in <code>additionalHeads</code>. It defines the * graph's set of tails to include all <code>Unit</code>s which represent * some sort of return bytecode or an <code>athrow</code> bytecode which may * escape the method. */ private void buildHeadsAndTails(Set<Unit> additionalHeads) { List<Unit> headList = new ArrayList<Unit>(additionalHeads.size() + 1); headList.addAll(additionalHeads); if (unitChain.isEmpty()) throw new IllegalStateException("No body for method " + body.getMethod().getSignature()); Unit entryPoint = unitChain.getFirst(); if (!headList.contains(entryPoint)) { headList.add(entryPoint); } List<Unit> tailList = new ArrayList<Unit>(); for (Unit u : unitChain) { if (u instanceof soot.jimple.ReturnStmt || u instanceof soot.jimple.ReturnVoidStmt || u instanceof soot.baf.ReturnInst || u instanceof soot.baf.ReturnVoidInst) { tailList.add(u); } else if (u instanceof soot.jimple.ThrowStmt || u instanceof soot.baf.ThrowInst) { Collection<ExceptionDest> dests = getExceptionDests(u); int escapeMethodCount = 0; for (ExceptionDest dest : dests) { if (dest.getTrap() == null) { escapeMethodCount++; } } if (escapeMethodCount > 0) { tailList.add(u); } } } tails = Collections.unmodifiableList(tailList); heads = Collections.unmodifiableList(headList); }
@Test public void testJThrowStmt() { // First test with an argument that is included in // PERENNIAL_THROW_EXCEPTIONS. ThrowStmt s = Jimple.v().newThrowStmt(Jimple.v().newLocal("local0", RefType.v("java.lang.NullPointerException"))); Set expectedRep = new ExceptionHashSet(utility.PERENNIAL_THROW_EXCEPTIONS); expectedRep.remove(utility.NULL_POINTER_EXCEPTION); expectedRep.add(AnySubType.v(utility.NULL_POINTER_EXCEPTION)); assertTrue(ExceptionTestUtility.sameMembers(expectedRep, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.PERENNIAL_THROW_EXCEPTIONS_PLUS_SUPERTYPES, utility.catchableSubset(unitAnalysis.mightThrow(s))); // Throw a local of type IncompatibleClassChangeError. Local local = Jimple.v().newLocal("local1", utility.INCOMPATIBLE_CLASS_CHANGE_ERROR); s.setOp(local); expectedRep = new ExceptionHashSet(utility.THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE); expectedRep.remove(utility.INCOMPATIBLE_CLASS_CHANGE_ERROR); expectedRep.add(AnySubType.v(utility.INCOMPATIBLE_CLASS_CHANGE_ERROR)); assertTrue(ExceptionTestUtility.sameMembers(expectedRep, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES_PLUS_SUPERTYPES, utility.catchableSubset(unitAnalysis.mightThrow(s))); // Throw a local of unknown type. local = Jimple.v().newLocal("local1", soot.UnknownType.v()); s.setOp(local); assertTrue(ExceptionTestUtility.sameMembers(utility.ALL_THROWABLES_REP, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.ALL_TEST_THROWABLES, utility.catchableSubset(unitAnalysis.mightThrow(s))); }
private SootClass findExceptionType(ThrowStmt s) { if (s.getOp() instanceof NewExpr) { NewExpr ne = (NewExpr) s.getOp(); return ne.getBaseType().getSootClass(); } else if (s.getOp() instanceof Local) { Local l = (Local) s.getOp(); if (l.getType() instanceof RefType) { return ((RefType) l.getType()).getSootClass(); } } // System.err.println("Unexpected value in throw stmt " + s.getOp()); return Scene.v().loadClass("java.lang.Throwable", SootClass.SIGNATURES); }
@Override public void caseThrowStmt(ThrowStmt arg0) { injectLabelStatements(arg0); // find the type of the exception that is thrown. SootClass c = findExceptionType(arg0); arg0.getOp().apply(this.valueswitch); Expression right = this.valueswitch.getExpression(); // assign the value from arg0.getOp() to the $exception variable of // the current procedure. // Note that this only works because soot moves the "new" statement // to a new local variable. AssignmentTranslation.translateAssignment(this, this.procInfo.getExceptionVariable(), right); // Add a goto statement to the exceptional successors. List<Trap> traps = new LinkedList<Trap>(); List<Trap> finally_traps = new LinkedList<Trap>(); // TODO: do we have TranslationHelpers.getReachableTraps(arg0, this.procInfo.getSootMethod(), traps, finally_traps); // TODO, maybe we need to consider the case that // we don't know the exact type of arg0.getOp at this point? for (Trap trap : traps) { if (GlobalsCache.v().isSubTypeOrEqual(c, trap.getException())) { this.boogieStatements.add(this.pf.mkGotoStatement(GlobalsCache .v().getUnitLabel((Stmt) trap.getHandlerUnit()))); return; } } this.boogieStatements.add(this.pf.mkReturnStatement()); }
public static boolean isBranch(Unit u){ if(u instanceof IfStmt || u instanceof GotoStmt || u instanceof SwitchStmt || u instanceof ThrowStmt || u instanceof ReturnStmt || u instanceof ReturnVoidStmt) return true; return false; }
private SootClass findExceptionType(ThrowStmt s) { if (s.getOp() instanceof NewExpr) { NewExpr ne = (NewExpr) s.getOp(); return ne.getBaseType().getSootClass(); } else if (s.getOp() instanceof Local) { Local l = (Local) s.getOp(); if (l.getType() instanceof RefType) { return ((RefType) l.getType()).getSootClass(); } } System.err.println("Unexpected value in throw stmt " + s.getOp()); return Scene.v().loadClass("java.lang.Throwable", SootClass.SIGNATURES); }
@Override public void caseThrowStmt(ThrowStmt stmt) { throw new RuntimeException("todo"); }
private void fixExceptions(SootMethod caller, Unit callSite, Set<SootClass> doneSet) { ThrowAnalysis ta = Options.v().src_prec() == Options.src_prec_apk ? DalvikThrowAnalysis.v() : UnitThrowAnalysis.v(); ThrowableSet throwSet = ta.mightThrow(callSite); for (final Trap t : caller.getActiveBody().getTraps()) if (doneSet.add(t.getException()) && throwSet.catchableAs(t.getException().getType())) { SootMethod thrower = exceptionThrowers.get(t.getException()); if (thrower == null) { if (exceptionClass == null) { exceptionClass = new SootClass("FLOWDROID_EXCEPTIONS", Modifier.PUBLIC); Scene.v().addClass(exceptionClass); } // Create the new method thrower = new SootMethod("throw" + exceptionThrowers.size(), Collections.<Type>emptyList(), VoidType.v()); thrower.setModifiers(Modifier.PUBLIC | Modifier.STATIC); final Body body = Jimple.v().newBody(thrower); thrower.setActiveBody(body); final SootMethod meth = thrower; IEntryPointCreator epc = new BaseEntryPointCreator() { @Override public Collection<String> getRequiredClasses() { return Collections.emptySet(); } @Override protected SootMethod createDummyMainInternal(SootMethod emptySootMethod) { LocalGenerator generator = new LocalGenerator(body); // Create the counter used for the opaque predicate int conditionCounter = 0; Value intCounter = generator.generateLocal(IntType.v()); AssignStmt assignStmt = new JAssignStmt(intCounter, IntConstant.v(conditionCounter)); body.getUnits().add(assignStmt); Stmt afterEx = Jimple.v().newNopStmt(); IfStmt ifStmt = Jimple.v().newIfStmt(Jimple.v().newEqExpr(intCounter, IntConstant.v(conditionCounter)), afterEx); body.getUnits().add(ifStmt); conditionCounter++; Local lcEx = generator.generateLocal(t.getException().getType()); AssignStmt assignNewEx = Jimple.v().newAssignStmt(lcEx, Jimple.v().newNewExpr(t.getException().getType())); body.getUnits().add(assignNewEx); InvokeStmt consNewEx = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(lcEx, Scene.v().makeConstructorRef(exceptionClass, Collections.<Type>emptyList()))); body.getUnits().add(consNewEx); ThrowStmt throwNewEx = Jimple.v().newThrowStmt(lcEx); body.getUnits().add(throwNewEx); body.getUnits().add(afterEx); return meth; } }; epc.createDummyMain(thrower); exceptionThrowers.put(t.getException(), thrower); exceptionClass.addMethod(thrower); } // Call the exception thrower after the old call site Stmt throwCall = Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(thrower.makeRef())); caller.getActiveBody().getUnits().insertBefore(throwCall, callSite); } }
public void caseThrowStmt(ThrowStmt stmt) { String varName = printValueAssignment(stmt.getOp(),"op"); printStmt(stmt, varName); }
public void caseThrowStmt(ThrowStmt stmt) { stmt.setOp(this.uv.visit( stmt.getOp(), RefType.v("java.lang.Throwable"), stmt)); }
public void caseThrowStmt(ThrowStmt stmt) { }
public ThrowableSet mightThrowImplicitly(ThrowStmt t) { return implicitThrowExceptions; }
@Override public void caseThrowStmt(ThrowStmt s) { result = mightThrowImplicitly(s); result = result.add(mightThrowExplicitly(s)); }
@Test public void testGThrowStmt() { ThrowStmt s = Grimp.v().newThrowStmt(Grimp.v().newLocal("local0", RefType.v("java.util.zip.ZipException"))); Set expectedRep = new ExceptionHashSet(utility.PERENNIAL_THROW_EXCEPTIONS); expectedRep.add(AnySubType.v(Scene.v().getRefType("java.util.zip.ZipException"))); assertTrue(ExceptionTestUtility.sameMembers(expectedRep, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); Set expectedCatch = new ExceptionHashSet(utility.PERENNIAL_THROW_EXCEPTIONS_PLUS_SUPERTYPES); // We don't need to add java.util.zip.ZipException, since it is not // in the universe of test Throwables. assertEquals(expectedCatch, utility.catchableSubset(unitAnalysis.mightThrow(s))); // Now throw a new IncompatibleClassChangeError. s = Grimp.v().newThrowStmt( Grimp.v().newNewInvokeExpr( utility.INCOMPATIBLE_CLASS_CHANGE_ERROR, Scene.v().makeMethodRef(utility.INCOMPATIBLE_CLASS_CHANGE_ERROR.getSootClass(), "void <init>", Collections.EMPTY_LIST, VoidType.v(), false), new ArrayList() ) ); assertTrue(ExceptionTestUtility.sameMembers(utility.THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUPERTYPES, utility.catchableSubset(unitAnalysis.mightThrow(s))); // Throw a local of type IncompatibleClassChangeError. Local local = Grimp.v().newLocal("local1", utility.INCOMPATIBLE_CLASS_CHANGE_ERROR); s.setOp(local); expectedRep = new ExceptionHashSet(utility.PERENNIAL_THROW_EXCEPTIONS); expectedRep.remove(utility.INCOMPATIBLE_CLASS_CHANGE_ERROR); expectedRep.add(AnySubType.v(utility.INCOMPATIBLE_CLASS_CHANGE_ERROR)); assertTrue(ExceptionTestUtility.sameMembers(expectedRep, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES_PLUS_SUPERTYPES, utility.catchableSubset(unitAnalysis.mightThrow(s))); // Throw a local of unknown type. local = Jimple.v().newLocal("local1", soot.UnknownType.v()); s.setOp(local); assertTrue(ExceptionTestUtility.sameMembers(utility.ALL_THROWABLES_REP, Collections.EMPTY_SET, unitAnalysis.mightThrow(s))); assertEquals(utility.ALL_TEST_THROWABLES, utility.catchableSubset(unitAnalysis.mightThrow(s))); }
private boolean isJumpStmt(Stmt st) { return ( st instanceof ThrowStmt || st instanceof GotoStmt || st instanceof ReturnStmt); }
public final void caseThrowStmt( ThrowStmt s) { statement = s; caseThrowStmt( (Local) s.getOp() ); }
boolean isStub(SootMethod method) { if(!method.isConcrete()) return false; PatchingChain<Unit> units = method.retrieveActiveBody().getUnits(); Unit unit = units.getFirst(); while(unit instanceof IdentityStmt) unit = units.getSuccOf(unit); //if method is <init>, then next stmt could be a call to super.<init> if(method.getName().equals("<init>")){ if(unit instanceof InvokeStmt){ if(((InvokeStmt) unit).getInvokeExpr().getMethod().getName().equals("<init>")) unit = units.getSuccOf(unit); } } if(!(unit instanceof AssignStmt)) return false; Value rightOp = ((AssignStmt) unit).getRightOp(); if(!(rightOp instanceof NewExpr)) return false; if(!((NewExpr) rightOp).getType().toString().equals("java.lang.RuntimeException")) return false; Local e = (Local) ((AssignStmt) unit).getLeftOp(); //may be there is an assignment (if soot did not optimized it away) Local f = null; unit = units.getSuccOf(unit); if(unit instanceof AssignStmt){ f = (Local) ((AssignStmt) unit).getLeftOp(); if(!((AssignStmt) unit).getRightOp().equals(e)) return false; unit = units.getSuccOf(unit); } //it should be the call to the constructor Stmt s = (Stmt) unit; if(!s.containsInvokeExpr()) return false; if(!s.getInvokeExpr().getMethod().getSignature().equals("<java.lang.RuntimeException: void <init>(java.lang.String)>")) return false; unit = units.getSuccOf(unit); if(!(unit instanceof ThrowStmt)) return false; Immediate i = (Immediate) ((ThrowStmt) unit).getOp(); return i.equals(e) || i.equals(f); }
/** * DOC * * @see soot.jimple.StmtSwitch#caseThrowStmt(soot.jimple.ThrowStmt) */ @Override public void caseThrowStmt(ThrowStmt stmt) { // TODO: Consider reaction stmt.getOp().apply(valueSwitch); }
@Override public void caseThrowStmt(ThrowStmt stmt) { throwNotImplementedException(stmt.getClass(), stmt.toString()); }
@Override public void caseThrowStmt(ThrowStmt stmt) { logger.fine("\n > > > Throw statement identified < < <"); valueSwitch.callingStmt = stmt; }
@Override public void caseThrowStmt(ThrowStmt stmt) { logger.fine("\n > > > Throw statement identified < < <"); }
/** * Method, which should process the given statement of type * {@link ThrowStmt}, but is not implemented in the current version of this * method. If method will be called an exception is thrown. * * @param stmt * Statement that should be processed to check for security * violations. * @see soot.jimple.StmtSwitch#caseThrowStmt(soot.jimple.ThrowStmt) * @throws UnimplementedSwitchException * Method throws always this exception, because the method is * not implemented. */ @Override public void caseThrowStmt(ThrowStmt stmt) { throw new SwitchException(getMsg("exception.analysis.switch.not_implemented", stmt.toString(), getSourceLine(), stmt.getClass().getSimpleName(), this.getClass().getSimpleName())); }
/** * Returns the set of all <code>Throwable</code>s as the set * of types that a <code>throw</code> statement may throw implicitly, * that is, the possible types of errors which might arise in * the course of executing the <code>throw</code> statement, rather * than the type of the <code>throw</code>'s operand. * * @param t the {@link ThrowStmt} whose exceptions are to be returned. * * @return the set of all <code>Throwable</code>s. */ public ThrowableSet mightThrowImplicitly(ThrowStmt t) { return ThrowableSet.Manager.v().ALL_THROWABLES; }
/** * Returns a set representing the {@link Throwable} types that * the specified throw statement might throw explicitly, that is, * the possible types for its <code>Throwable</code> argument. * * @param t {@link ThrowStmt} whose explicit exceptions are * to be returned. * * @return a representation of the possible types of * <code>t</code>'s <code>Throwable</code> operand. */ ThrowableSet mightThrowExplicitly(ThrowStmt t);
/** * Returns a set representing the {@link Throwable} types that * the specified throw statement might throw implicitly, that is, * the possible types of errors which might arise in the course * of executing the <code>throw</code> statement, rather than * the type of the <code>throw</code>'s operand. * * @param t {@link ThrowStmt} whose implicit exceptions are * to be returned. * * @return a representation of the types of exceptions that * <code>t</code> might throw implicitly. */ ThrowableSet mightThrowImplicitly(ThrowStmt t);
abstract public ThrowableSet mightThrowImplicitly(ThrowStmt t);