/** * For a concrete method (declared in an application class), find statements containing an invoke * expression for which the method is one of the method in 'allEventInformation' (i.e., * getLine1Number(), ...). * * @param cfg */ private void doAccessControlChecks(BiDiInterproceduralCFG<Unit, SootMethod> cfg) { for (SootClass sc : Scene.v().getApplicationClasses()) { for (SootMethod sm : sc.getMethods()) { if (sm.isConcrete()) { Body body = sm.retrieveActiveBody(); // only instrument application methods (i.e., not methods declared in PEP helper classes // or in a Java library classes or in an Android classes, ...) if (isInstrumentationNecessary(sm)) { // important to use snapshotIterator here Iterator<Unit> i = body.getUnits().snapshotIterator(); log.debug("method: " + sm); while (i.hasNext()) { Stmt s = (Stmt) i.next(); if (s.containsInvokeExpr()) { InvokeExpr invExpr = s.getInvokeExpr(); String methodSignature = invExpr.getMethod().getSignature(); if (allEventInformation.containsKey(methodSignature)) { log.debug("statement " + s + " matches " + methodSignature + "."); ResultSinkInfo sink = null; outer: for (ResultSinkInfo key : results.getResults().keySet()) { // iterate over all the arguments of the invoke expression // and check if an argument is a tainted sink. If one is // set variable 'sink' to the ResultSinkInfo key. for (Value v : invExpr.getArgs()) { Value pathValue = key.getAccessPath().getPlainValue(); if (v == pathValue) { sink = key; log.debug("found a sink: " + pathValue); break outer; } } } if (sink != null) { log.debug("instrument with data flow information )" + s + ")"); instrumentSourceToSinkConnections(cfg, sink, s instanceof AssignStmt); instrumentWithNoDataFlowInformation( methodSignature, s, invExpr, body, s instanceof AssignStmt); } else { log.debug("instrument without data flow information (" + s + ")"); instrumentWithNoDataFlowInformation( methodSignature, s, invExpr, body, s instanceof AssignStmt); } } } // if stmt containts invoke expression } // loop on statements } } } } }
/** * Make sure that all invoke special targets are cloned into the class from ancestors. This might * mean that we have to clone hidden methods, and change their names. So clone them in, and update * the clone to original map, and update the invoke special Also, this will update invoke specials * that target methods cloned in previous call to above cloneReachableNonHiddenAncestorMethods() */ private void cloneHiddenAncestorMethodsAndFixInvokeSpecial() { Set<SootClass> parents = SootUtils.getParents(clazz); boolean debug = false; // (clazz.getName().contains("ResultDisplayer")); boolean cloneAdded = false; do { cloneAdded = false; for (SootMethod method : clazz.getMethods()) { if (method.isAbstract() || method.isPhantom() || !method.isConcrete()) continue; if (debug) System.out.println(method); Body body = null; try { body = method.retrieveActiveBody(); } catch (Exception ex) { logger.info("Exception retrieving method body {}", ex); continue; } StmtBody stmtBody = (StmtBody) body; Chain units = stmtBody.getUnits(); Iterator stmtIt = units.iterator(); while (stmtIt.hasNext()) { Stmt stmt = (Stmt) stmtIt.next(); if (stmt.containsInvokeExpr() && stmt.getInvokeExpr() instanceof SpecialInvokeExpr) { SpecialInvokeExpr si = (SpecialInvokeExpr) stmt.getInvokeExpr(); SootMethod target = resolveSpecialInvokeTarget(si); // si.getMethod(); if (debug) System.out.printf("\t%s %s", si, target); if (clonedToOriginal.values().contains(target)) { // found target of invoke special, and it has been cloned, so change the invoke // special SootMethod cloneOfTarget = clonedToOriginal.inverse().get(target); si.setMethodRef(cloneOfTarget.makeRef()); if (debug) System.out.println("\tChange ref " + cloneOfTarget); } else if (parents.contains(target.getDeclaringClass())) { // target has not been cloned, but should be cloned, so clone it and change ref of // invoke String name = target.getName() + CLONED_METHOD_SUFFIX + (cloned_method_id++); SootMethod clonedMethod = cloneMethod(target, name); si.setMethodRef(clonedMethod.makeRef()); cloneAdded = true; if (debug) System.out.println("\tClone and Change ref " + clonedMethod); } } } } } while (cloneAdded); }
@Override public String toString() { StringBuilder sb = new StringBuilder(context.toString()); if (context.hasTag("LineNumberTag")) sb.append(" on line ") .append(((LineNumberTag) context.getTag("LineNumberTag")).getLineNumber()); return sb.toString(); }
public static boolean isTarget( AnalysisDirection direction, SootMethod enclosingMethod, Unit unit, Iterable<AnalysisTarget> targets) { if (!(unit instanceof AssignStmt)) return false; Stmt s = (Stmt) unit; if (!s.containsInvokeExpr()) return false; InvokeExpr ie = s.getInvokeExpr(); for (AnalysisTarget target : targets) { if (target.matches(direction, enclosingMethod, ie)) return true; } return false; }
private void dumpTextGraph(SootMethod caller, PrintStream printStream, int level) { String indent = indentString(level); caller.getTags(); printStream.printf("%s %s\n", indent, caller.toString()); Iterator<Edge> iterator = callGraph.edgesOutOf(caller); callgraphSet.add(caller); // boolean appClass = caller.getDeclaringClass().isApplicationClass(); boolean systemApi = API.v().isSystemMethod(caller); /* printStream.printf("%s Declaring method %s: app %s\n", indent, caller.toString(), systemApi? "False": "True"); */ String subindent = indentString(level + 1); Set<Object> calleeSet = new HashSet<Object>(); while (iterator != null && iterator.hasNext()) { Edge edge = iterator.next(); if (!systemApi) { List<Stmt> invokeStmtList = SootUtils.getInvokeStatements(caller, edge.tgt()); for (Stmt stmt : invokeStmtList) { if (calleeSet.contains(stmt)) continue; printStream.printf("%s #[%s] ", subindent, stmt); SourceLocationTag tag = SootUtils.getSourceLocation(stmt); if (tag != null) { printStream.printf(": %s", tag.toString()); } printStream.printf("\n"); calleeSet.add(stmt.toString()); } } if (!callgraphSet.contains(edge.tgt())) { dumpTextGraph(edge.tgt(), printStream, level + 1); } else { // already in the call graph, just print it out if (calleeSet.contains(edge.tgt())) continue; printStream.printf("%s %s\n", subindent, edge.tgt().toString()); calleeSet.add(edge.tgt()); } } }
/** Dumps out the call chain in json format * */ public void dump_json(PrintStream fp, String indent) { fp.printf("%s{ %s,\n", indent, json_field("type", type)); fp.printf("%s %s,\n", indent, json_field("link", link)); String sig = method.getSignature(); fp.printf("%s %s,\n", indent, json_field("signature", sig)); if (stmt != null) { SootMethodRef invoke = stmt.getInvokeExpr().getMethodRef(); String invokeSig; try { SootMethod concrete = SootUtils.resolve(stmt.getInvokeExpr().getMethodRef()); invokeSig = concrete.getSignature(); } catch (CannotFindMethodException e1) { logger.debug("Cannot find concrete method for {} in SourceCallChainInfo.dump_json()", stmt); invokeSig = invoke.getSignature(); } if (!invokeSig.equals(sig)) { fp.printf("%s %s,\n", indent, json_field("source-signature", invokeSig)); } } SourceLocationTag slt = (stmt == null) ? SootUtils.getMethodLocation(method) : getSourceLocation(stmt); if (slt != null) { fp.printf("%s %s", indent, json_field("src-loc")); fp.printf( "{ %s, %s},\n", json_field("class", slt.getClz()), json_field("line", slt.getLine())); } fp.printf("%s %s,\n", indent, json_field("syscalls", syscalls)); fp.printf("%s %s,\n", indent, json_field("calls", calls)); if ((contents != null) && (contents.length > 0)) { fp.printf("%s %s,\n", indent, json_field("score", score)); fp.printf("%s %s [\n", indent, json_field("contents")); String delim = ""; for (SourceCallChainInfo cci : contents) { fp.print(delim); delim = ",\n"; cci.dump_json(fp, indent + " "); } fp.printf("\n%s]}", indent); } else { fp.printf("%s %s\n", indent, json_field("score", score)); fp.printf("%s}", indent); } }
public static boolean isDifferentStartEndPos(Stmt s) { List<Tag> tags = s.getTags(); for (Tag tag : tags) { if (tag instanceof SourceLnNamePosTag) { SourceLnNamePosTag lineTag = (SourceLnNamePosTag) tag; if (lineTag.startLn() != lineTag.endLn()) return true; else return false; } } return false; }
@SuppressWarnings({"unchecked", "rawtypes"}) private Set<SootField> collectBlockField(JavaCriticalSection cs) { Set result = new HashSet(); int startLine = cs.getStartLine(); int endLine = cs.getEndline(); Body body = cs.getSootMethod().getActiveBody(); PatchingChain<Unit> units = body.getUnits(); for (Unit u : units) { Stmt s = (Stmt) u; LineNumberTag linetag = (LineNumberTag) s.getTag("LineNumberTag"); if (linetag == null) continue; int line = linetag.getLineNumber(); if (line < startLine || line > endLine) { continue; } List<ValueBox> Fieldslist = u.getUseBoxes(); Fieldslist.addAll(u.getDefBoxes()); for (ValueBox box : Fieldslist) { Value v = box.getValue(); if (v instanceof JInstanceFieldRef) { result.add(((JInstanceFieldRef) v).getField()); } } if (s.containsInvokeExpr()) { // 用调用图获得调用目标 Callees callees = new Callees(getCallGragh(), u); for (SootMethod invokeMethod : callees.explicits()) { if (invokeMethod == null) continue; Collection use = scaner.getUseInstanceFields(invokeMethod); Collection mod = new HashSet(); if (needMod) { mod.addAll(scaner.getModInstanceFields(invokeMethod)); } if (use != null) result.addAll(use); result.addAll(mod); } } } return result; }
@Override public Type appliesInternal(AndroidMethod method) { SootMethod sm = getSootMethod(method); if (sm == null) { System.err.println("Method not declared: " + method); return Type.NOT_SUPPORTED; } // We are only interested in setters if (!sm.isConcrete()) return Type.NOT_SUPPORTED; try { Set<Value> paramVals = new HashSet<Value>(); for (Unit u : sm.retrieveActiveBody().getUnits()) { // Collect the parameters if (u instanceof IdentityStmt) { IdentityStmt id = (IdentityStmt) u; if (id.getRightOp() instanceof ParameterRef) paramVals.add(id.getLeftOp()); } // Check for invocations if (u instanceof Stmt) { Stmt stmt = (Stmt) u; if (stmt.containsInvokeExpr()) if (stmt.getInvokeExpr() instanceof InstanceInvokeExpr) { InstanceInvokeExpr iinv = (InstanceInvokeExpr) stmt.getInvokeExpr(); if (paramVals.contains(iinv.getBase())) if (iinv.getMethod().getName().startsWith(methodName)) return Type.TRUE; } } } return Type.FALSE; } catch (Exception ex) { System.err.println("Something went wrong:"); ex.printStackTrace(); return Type.NOT_SUPPORTED; } }
/** @apilevel low-level */ public void flushCache() { super.flushCache(); isDAafter_Variable_values = null; isDUafter_Variable_values = null; canCompleteNormally_computed = false; typeNullPointerException_computed = false; typeNullPointerException_value = null; handlesException_TypeDecl_values = null; typeThrowable_computed = false; typeThrowable_value = null; typeNull_computed = false; typeNull_value = null; }
/** * Returns basic block that contains the statement, or null. If id stmt, it looks in tag of first * non-id stmt. */ public static Block getBB(Stmt s) { Block bb; // 2010-02-26: return null when s == null if (s != null) { // move to first non-id stmt Stmt sNonId = s; if (sNonId instanceof IdentityStmt) { PatchingChain pchain = ProgramFlowGraph.inst().getContainingMethod(sNonId).retrieveActiveBody().getUnits(); do { sNonId = (Stmt) pchain.getSuccOf(sNonId); } while (sNonId instanceof IdentityStmt); } // retrieve basic block for non-id stmt StmtTag sTag = (StmtTag) sNonId.getTag(StmtTag.TAG_NAME); bb = sTag.getBasicBlock(); } else { bb = null; } return bb; }
public static int getStatementLineNumber(Stmt s) { List<Tag> tags = s.getTags(); int line = -1; for (Tag tag : tags) { if (tag instanceof SourceLnNamePosTag) { SourceLnNamePosTag lineTag = (SourceLnNamePosTag) tag; line = lineTag.startLn(); } else if (tag instanceof LineNumberTag) { LineNumberTag lineTag = (LineNumberTag) tag; line = lineTag.getLineNumber(); } } return line; }
/** * Given the merge of the <code>out</code> sets, compute the <code>in</code> set for <code>d * </code>. * * <p>Processes the analysis for the given {@link Unit}, i.e. checks the end of an implicit flow * for the given unit and after that tries to apply a {@link SecurityLevelStmtSwitch} switch to * the statement, i.e. calculates or updates the <em>security levels</em> of the statement * components to check for security violations. * * @param in Current incoming map of the local variables for the given unit. * @param d The current unit which should be checked for security violations. * @param out Current outgoing map of the local variables for the given unit. * @see soot.toolkits.scalar.FlowAnalysis#flowThrough(java.lang.Object, java.lang.Object, * java.lang.Object) * @see SecurityLevelStmtSwitch */ @Override protected void flowThrough(LocalsMap in, Unit d, LocalsMap out) { copy(in, out); Stmt stmt = (Stmt) d; getAnalyzedEnvironment().setStmt(stmt); checkEndOfImplicitFlow(stmt, in, out); try { SecurityLevelStmtSwitch stmtSwitch = new SecurityLevelStmtSwitch(getAnalyzedEnvironment(), getStore(), in, out); stmt.apply(stmtSwitch); } catch (ProgramCounterException | EnvironmentNotFoundException | SwitchException | MethodParameterNotFoundException | LevelNotFoundException e) { throw new AnalysisException( getMsg( "exception.analysis.other.error_switch", stmt.toString(), getSignatureOfMethod(getAnalyzedEnvironment().getSootMethod()), getAnalyzedEnvironment().getSrcLn()), e); } }
private int numMatchArgs(int numFormals, UnchangedParamsAnalysis mrpa, Stmt s) { FlowSet before = (FlowSet) mrpa.getFlowBefore(s); List args = ((InvokeExpr) s.getInvokeExpr()).getArgs(); int matchArg = 0; for (int i = 0; i < numFormals; i++) { Value arg = (Value) args.get(i); for (Iterator rppIt = before.iterator(); rppIt.hasNext(); ) { IDValuePair rpp = (IDValuePair) rppIt.next(); if (rpp.groupID == i && arg.equivTo(rpp.value)) { matchArg++; break; } } } return matchArg; }
public static List<Value> getAllImmediateValue(Stmt stmt) { List<Value> rtVal = new ArrayList<Value>(); List<ValueBox> vbs = stmt.getUseAndDefBoxes(); Set<String> frs = new HashSet<String>(); for (ValueBox vb : vbs) { Value v = vb.getValue(); if (v instanceof FieldRef) { int endPos = v.toString().indexOf('.'); String name = v.toString().substring(0, endPos); frs.add(name); Value existV = null; for (ValueBox vBox : vbs) { if (name.equals(vBox.getValue().toString())) { existV = vBox.getValue(); break; } } if (null != existV) { rtVal.remove(existV); } rtVal.add(v); } if (v instanceof Immediate) { if (!frs.contains(v.toString())) { rtVal.add(v); } } } return rtVal; }
public void internalTransform(String phaseName, Map opts) { Iterator it = Scene.v().getApplicationClasses().iterator(); while (it.hasNext()) { SootClass sc = (SootClass) it.next(); // make map of first line to each method HashMap<Integer, SootMethod> lineToMeth = new HashMap<Integer, SootMethod>(); Iterator methIt = sc.getMethods().iterator(); while (methIt.hasNext()) { SootMethod meth = (SootMethod) methIt.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); lineToMeth.put(new Integer(tag.getLineNumber()), meth); } } Iterator methIt2 = sc.getMethods().iterator(); while (methIt2.hasNext()) { SootMethod meth = (SootMethod) methIt2.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); int line_num = tag.getLineNumber() - 1; // already taken if (lineToMeth.containsKey(new Integer(line_num))) { meth.addTag(new LineNumberTag(line_num + 1)); } // still available - so use it for this meth else { meth.addTag(new LineNumberTag(line_num)); } } } } }
/** * @ast method * @aspect AnonymousClasses * @declaredat * /Users/eric/Documents/workspaces/clara-soot/JastAddJ/Java1.4Frontend/AnonymousClasses.jrag:207 */ protected void collectExceptions(Collection c, ASTNode target) { super.collectExceptions(c, target); TypeDecl exceptionType = getExpr().type(); if (exceptionType == typeNull()) exceptionType = typeNullPointerException(); c.add(exceptionType); }
/** * @param cfg * @param sink * @param assignmentStatement */ private void instrumentSourceToSinkConnections( BiDiInterproceduralCFG<Unit, SootMethod> cfg, ResultSinkInfo sink, boolean assignmentStatement) { sourceSinkConnectionCounter += 1; // loop through the sinks for (ResultSinkInfo key : results.getResults().keySet()) { log.debug("compare: " + key); log.debug(" to: " + sink); // if the current sink is the sink at the unit tagged with 'sink' if (key.equals(sink)) { // loop through the sources for (ResultSourceInfo si : results.getResults().get(key)) { Stmt stmt = si.getSource(); SootMethod sm = cfg.getMethodOf(stmt); Body body = sm.retrieveActiveBody(); // Source instrumentation. The three type categories for the source are: // - callback // - ICC source method (i.e., Intent.getExtras()) // - not a callback and not an ICC source method (i.e., getLine1Number()) // if (isInterComponentSourceCallback(si, cfg)) { throw new RuntimeException("Callbacks as sources are not supported right now"); } else if (isInterComponentSourceNoCallback(si, cfg)) { // only invoke expression are treated here if (stmt.containsInvokeExpr()) { // only statements that return a android.os.Bundle are currently supported if (stmt instanceof DefinitionStmt) { DefinitionStmt defStmt = (DefinitionStmt) stmt; Value leftValue = defStmt.getLeftOp(); if (leftValue.getType().equals(RefType.v("android.os.Bundle"))) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("android.os.Bundle")); args.add(leftValue); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) { instrumentationPoint = getLastIdentityStmt(body); } else { instrumentationPoint = stmt; } body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert a: " + invStmt); } else { System.err.println("We do only support android.os.Bundle right now!"); } } } } else { String sourceCat = getSourceCategory(si); if (sourceCat != null) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("java.lang.String")); args.add(StringConstant.v(sourceCat)); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) instrumentationPoint = getLastIdentityStmt(body); else instrumentationPoint = stmt; body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert b: " + invStmt); } } // sink instrumentation if (sink.getSink().containsInvokeExpr()) { Body bodyOfSink = cfg.getMethodOf(key.getSink()).getActiveBody(); InvokeExpr invExpr = sink.getSink().getInvokeExpr(); List<Unit> generated = new ArrayList<Unit>(); generated.addAll( instrumentIntentAddings(cfg, stmt, invExpr, results.getResults().get(key))); EventInformation sinkEventInfo = allEventInformation.get(invExpr.getMethod().getSignature()); EventInformation sourceEventInfo = allEventInformation.get(si.getSource().getInvokeExpr().getMethod().getSignature()); generated.addAll( generatePolicyEnforcementPoint( key.getSink(), invExpr, bodyOfSink, sourceSinkConnectionCounter, assignmentStatement)); log.debug("body with data flow:\n" + body); for (Unit u : generated) { log.debug("gen: " + u); } if (sinkEventInfo.isInstrumentAfterStatement()) bodyOfSink.getUnits().insertAfter(generated, key.getSink()); else bodyOfSink.getUnits().insertBefore(generated, key.getSink()); } else throw new RuntimeException("Double-Check the assumption"); } // loop through the sources } // if the sink at the unit is the current sink } // loop through the sinks }
/** * This method pushes all newExpr down to be the stmt directly before every invoke of the init * only if they are in the types list */ public void internalTransform(Body b, String phaseName, Map options) { JimpleBody body = (JimpleBody) b; if (Options.v().verbose()) G.v().out.println("[" + body.getMethod().getName() + "] Folding Jimple constructors..."); Chain units = body.getUnits(); List<Unit> stmtList = new ArrayList<Unit>(); stmtList.addAll(units); Iterator<Unit> it = stmtList.iterator(); Iterator<Unit> nextStmtIt = stmtList.iterator(); // start ahead one nextStmtIt.next(); SmartLocalDefs localDefs = SmartLocalDefsPool.v().getSmartLocalDefsFor(body); UnitGraph graph = localDefs.getGraph(); LocalUses localUses = new SimpleLocalUses(graph, localDefs); /* fold in NewExpr's with specialinvoke's */ while (it.hasNext()) { Stmt s = (Stmt) it.next(); if (!(s instanceof AssignStmt)) continue; /* this should be generalized to ArrayRefs */ // only deal with stmts that are an local = newExpr Value lhs = ((AssignStmt) s).getLeftOp(); if (!(lhs instanceof Local)) continue; Value rhs = ((AssignStmt) s).getRightOp(); if (!(rhs instanceof NewExpr)) continue; // check if very next statement is invoke --> // this indicates there is no control flow between // new and invoke and should do nothing if (nextStmtIt.hasNext()) { Stmt next = (Stmt) nextStmtIt.next(); if (next instanceof InvokeStmt) { InvokeStmt invoke = (InvokeStmt) next; if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) { SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke.getInvokeExpr(); if (invokeExpr.getBase() == lhs) { break; } } } } // check if new is in the types list - only process these if (!types.contains(((NewExpr) rhs).getType())) continue; List lu = localUses.getUsesOf(s); Iterator luIter = lu.iterator(); boolean MadeNewInvokeExpr = false; while (luIter.hasNext()) { Unit use = ((UnitValueBoxPair) (luIter.next())).unit; if (!(use instanceof InvokeStmt)) continue; InvokeStmt is = (InvokeStmt) use; if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr) || lhs != ((SpecialInvokeExpr) is.getInvokeExpr()).getBase()) continue; // make a new one here AssignStmt constructStmt = Jimple.v() .newAssignStmt(((DefinitionStmt) s).getLeftOp(), ((DefinitionStmt) s).getRightOp()); constructStmt.setRightOp(Jimple.v().newNewExpr(((NewExpr) rhs).getBaseType())); MadeNewInvokeExpr = true; // redirect jumps use.redirectJumpsToThisTo(constructStmt); // insert new one here units.insertBefore(constructStmt, use); constructStmt.addTag(s.getTag("SourceLnPosTag")); } if (MadeNewInvokeExpr) { units.remove(s); } } }
public static boolean isCtorCall(Stmt s) { return s.containsInvokeExpr() && (s.getInvokeExpr() instanceof SpecialInvokeExpr) && s.getInvokeExpr().getMethod().getName().equals("<init>"); }
/** * @param g * @param numFormals number of parameters need to be taken into account, since abc will generate * auxiliary parameters for proceed call, so this analysis needs the number of parameters * originly declared in around advice * @param withReturn if the around adivce has return value */ public ProceedAnalysis(UnitGraph g, int numFormals, boolean withReturn) { super(g); this.g = g; exactProceedSet = new HashSet<Stmt>(); nonExactProceedSet = new HashSet<Stmt>(); UnchangedParamsAnalysis paramAnalysis = null; // if numformals = 0, dont need paramAnalysis if (numFormals >= 0) paramAnalysis = new UnchangedParamsAnalysis(g, numFormals); UnchangedReturnAnalysis returnAnalysis = new UnchangedReturnAnalysis(g); ExceptionBeforeProceedAnalysis exceptionAnalysis = new ExceptionBeforeProceedAnalysis(g); // calcualte exactProceedSet and nonExactProceedSet for (Iterator uIt = g.getBody().getUnits().iterator(); uIt.hasNext(); ) { Unit unit = (Unit) uIt.next(); if (unit instanceof Stmt) { Stmt s = (Stmt) unit; if (withReturn) { // care only AssignStmt if (s instanceof AssignStmt && s.containsInvokeExpr() && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) { boolean exact = false; int matchArg = numFormals; // if numformals = 0, dont need paramAnalysis analysis if (numFormals > 0) { matchArg = numMatchArgs(numFormals, paramAnalysis, s); } // System.out.println("invoke match arg = " + matchArg); if (matchArg == numFormals) { // should check return value and exceptions if (returnAnalysis.isReachReturn(s)) { if (!exceptionAnalysis.hasExceptionBefore(s)) { exact = true; } } } if (exact) exactProceedSet.add(s); else nonExactProceedSet.add(s); } } else { // care only InvokeStmt if (s instanceof InvokeStmt && s.containsInvokeExpr() && ImpactUtil.isProceed(((InvokeExpr) s.getInvokeExpr()).getMethod())) { boolean exact = false; int matchArg = numFormals; // if numformals = 0, dont need paramAnalysis analysis if (numFormals > 0) { matchArg = numMatchArgs(numFormals, paramAnalysis, s); } // System.out.println("invoke match arg = " + matchArg); if (matchArg == numFormals) { // should check exceptions if (!exceptionAnalysis.hasExceptionBefore(s)) { exact = true; } } if (exact) exactProceedSet.add(s); else nonExactProceedSet.add(s); } } } } doAnalysis(); }
public void assureAllSyncInCallGraph(Collection<JavaCriticalSection> criticalSections) { System.out.println("[assureAllSyncInCallgraph] starting"); Date start = new Date(); ReachableMethods oldReach = Scene.v().getReachableMethods(); // Collection et = EntryPoints.v().all(); // ReachableMethods reachableFromMain = new ReachableMethods(cg, et); // reachableFromMain.update(); Set<SootMethod> notInCG = new HashSet<SootMethod>(); for (JavaCriticalSection cs : criticalSections) { SootMethod m = cs.getSootMethod(); if (!oldReach.contains(m)) notInCG.add(m); } Set<SootMethod> alreadyInCG = new HashSet<SootMethod>(); for (Iterator<MethodOrMethodContext> it = oldReach.listener(); it.hasNext(); ) { alreadyInCG.add(it.next().method()); } /* * for(Iterator<?> it=cg.sourceMethods();it.hasNext();){ SootMethod m = * (SootMethod)it.next(); alreadyInCG.add(m); if(notInCG.contains(m)){ * notInCG.remove(m); } } */ // add new methods to the call graph Stack<SootMethod> worklist = new Stack<SootMethod>(); for (SootMethod m : notInCG) { worklist.push(m); } while (!worklist.isEmpty()) { SootMethod m = worklist.pop(); if (alreadyInCG.contains(m) || m == null) { continue; } alreadyInCG.add(m); Body body = m.retrieveActiveBody(); for (Unit u : body.getUnits()) { if (!(u instanceof Stmt)) { continue; } Stmt s = (Stmt) u; if (!s.containsInvokeExpr()) { continue; } InvokeExpr invoke = s.getInvokeExpr(); SootMethod declCallee = invoke.getMethod(); Collection<SootMethod> targets = new ArrayList<SootMethod>(); if (declCallee.isStatic()) { targets.add(declCallee); } else { // XXX: pay attention to reflexive call, thread call, and // etc. // Here we do not add edges for implicit targets, as these // parts of methods is not reachable // from the entry, and they will most likely to be analyzed // in a very conservative ways. InstanceInvokeExpr iie = (InstanceInvokeExpr) invoke; Local receiver = (Local) iie.getBase(); NumberedString subSig = iie.getMethodRef().getSubSignature(); if (invoke instanceof SpecialInvokeExpr) { SootMethod tgt = VirtualCalls.v().resolveSpecial((SpecialInvokeExpr) invoke, subSig, m); targets.add(tgt); } else { Type t = receiver.getType(); if (t instanceof ArrayType) { // t = RefType.v("java.lang.Object"); targets.add(declCallee); } // BottomType bug else if (t instanceof soot.jimple.toolkits.typing.fast.BottomType) { System.out.println("BottomType:" + s); } else if (t instanceof soot.NullType) { System.out.println("NullType:" + s); } else { SootClass c = ((RefType) t).getSootClass(); // Soot has a type resolving bug, and here may be // exceptions try { Set<SootMethod> callees = Scene.v().getOrMakeFastHierarchy().resolveAbstractDispatch(c, declCallee); targets.addAll(callees); } catch (Exception e) { System.out.println(e.getMessage()); } } } } for (SootMethod t : targets) { // add call edge Edge e = new Edge(m, s, t); Scene.v().getCallGraph().addEdge(e); // add to worklist if (t.isConcrete() && !alreadyInCG.contains(t)) { worklist.push(t); } } } } // infer entries for the methods not reachable from main entry List<SootMethod> entries = Scene.v().getEntryPoints(); _patchedEntries = new ArrayList<SootMethod>(notInCG); for (SootMethod m : notInCG) { // XXX there can be recursive calls, so for simple processing, all // methods not in old // call graph should be added to the entry. Checking the // non-existence of incoming edges // may miss some recursively called methods // if(!cg.edgesInto(m).hasNext()){ entries.add(m); // } } // update reachable methods Scene.v().setReachableMethods(null); }
private static String finegrainedFlowResults() { int totalReachableIfs = 0; int taintedReachableIfs = 0; int totalCountOfTaintSets = 0; int totalSizeOfTaintSets = 0; long totalValues = 0; Set<InfoValue> allSrcs = new HashSet<InfoValue>(); Set<Set<InfoValue>> allSrcSets = new HashSet<Set<InfoValue>>(); StringBuffer buf = new StringBuffer(); for (MethodOrMethodContext momc : PTABridge.v().getReachableMethodContexts()) { // reset counted locals for each method Set<Value> countedLocals = new HashSet<Value>(); SootMethod method = momc.method(); if (!method.isConcrete()) continue; try { Body body = method.retrieveActiveBody(); Iterator<Unit> unitIt = body.getUnits().snapshotIterator(); while (unitIt.hasNext()) { Stmt stmt = (Stmt) unitIt.next(); for (ValueBox vb : stmt.getUseAndDefBoxes()) { Value v = vb.getValue(); if (countedLocals.contains(v)) continue; countedLocals.add(v); Set<InfoValue> taints = getTaintSet(v, momc); if (taints != null) totalValues++; if (taints != null && !taints.isEmpty()) { allSrcs.addAll(taints); totalCountOfTaintSets++; totalSizeOfTaintSets += taints.size(); if (!allSrcSets.contains(taints)) allSrcSets.add(taints); countedLocals.add(v); } } if (stmt instanceof IfStmt) { totalReachableIfs++; boolean hasTainted = false; for (ValueBox vb : stmt.getUseBoxes()) { Value v = vb.getValue(); Set<InfoValue> taints = getTaintSet(v, momc); if (taints != null && !taints.isEmpty()) { hasTainted = true; break; } } totalReachableIfs++; if (hasTainted) { taintedReachableIfs++; } } } } catch (Exception e) { // ignore and continue } } buf.append("Tainted Reachable if statements: " + taintedReachableIfs + "\n"); buf.append("Total Reachable if Statements: " + totalReachableIfs + "\n"); buf.append( "Count of non-zero taint sets for primitives and strings: " + totalCountOfTaintSets + "\n"); buf.append( "Total distinct reachable primitives or string values in code: " + totalValues + "\n"); buf.append( "Total size of non-zero taint sets for primitives and strings: " + totalSizeOfTaintSets + "\n"); buf.append("Count of distinct sources: " + allSrcs.size() + "\n"); buf.append("Total distinct source sets: " + allSrcSets.size() + "\n"); return buf.toString(); }
public void flushCollectionCache() { super.flushCollectionCache(); }
public void flushCache() { super.flushCache(); isDAafter_Variable_values = null; isDUafter_Variable_values = null; canCompleteNormally_computed = false; }
private static boolean internalAggregate( StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) { LocalUses localUses; LocalDefs localDefs; ExceptionalUnitGraph graph; boolean hadAggregation = false; Chain<Unit> units = body.getUnits(); graph = new ExceptionalUnitGraph(body); localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph)); localUses = new SimpleLocalUses(graph, localDefs); List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false); for (Unit u : unitList) { if (!(u instanceof AssignStmt)) continue; AssignStmt s = (AssignStmt) u; Value lhs = s.getLeftOp(); if (!(lhs instanceof Local)) continue; Local lhsLocal = (Local) lhs; if (onlyStackVars && !lhsLocal.getName().startsWith("$")) continue; List<UnitValueBoxPair> lu = localUses.getUsesOf(s); if (lu.size() != 1) continue; UnitValueBoxPair usepair = lu.get(0); Unit use = usepair.unit; ValueBox useBox = usepair.valueBox; List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use); if (ld.size() != 1) continue; // Check to make sure aggregation pair in the same zone if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) { continue; } /* we need to check the path between def and use */ /* to see if there are any intervening re-defs of RHS */ /* in fact, we should check that this path is unique. */ /* if the RHS uses only locals, then we know what to do; if RHS has a method invocation f(a, b, c) or field access, we must ban field writes, other method calls and (as usual) writes to a, b, c. */ boolean cantAggr = false; boolean propagatingInvokeExpr = false; boolean propagatingFieldRef = false; boolean propagatingArrayRef = false; ArrayList<FieldRef> fieldRefList = new ArrayList<FieldRef>(); LinkedList<Value> localsUsed = new LinkedList<Value>(); for (ValueBox vb : s.getUseBoxes()) { Value v = vb.getValue(); if (v instanceof Local) localsUsed.add(v); else if (v instanceof InvokeExpr) propagatingInvokeExpr = true; else if (v instanceof ArrayRef) propagatingArrayRef = true; else if (v instanceof FieldRef) { propagatingFieldRef = true; fieldRefList.add((FieldRef) v); } } // look for a path from s to use in graph. // only look in an extended basic block, though. List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use); if (path == null) continue; Iterator<Unit> pathIt = path.iterator(); // skip s. if (pathIt.hasNext()) pathIt.next(); while (pathIt.hasNext() && !cantAggr) { Stmt between = (Stmt) (pathIt.next()); if (between != use) { // Check for killing definitions for (ValueBox vb : between.getDefBoxes()) { Value v = vb.getValue(); if (localsUsed.contains(v)) { cantAggr = true; break; } if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { if (v instanceof FieldRef) { if (propagatingInvokeExpr) { cantAggr = true; break; } else if (propagatingFieldRef) { // Can't aggregate a field access if passing a definition of a field // with the same name, because they might be aliased for (FieldRef fieldRef : fieldRefList) { if (((FieldRef) v).getField() == fieldRef.getField()) { cantAggr = true; break; } } } } else if (v instanceof ArrayRef) { if (propagatingInvokeExpr) { // Cannot aggregate an invoke expr past an array write cantAggr = true; break; } else if (propagatingArrayRef) { // cannot aggregate an array read past a write // this is somewhat conservative // (if types differ they may not be aliased) cantAggr = true; break; } } } } // Make sure not propagating past a {enter,exit}Monitor if (propagatingInvokeExpr && between instanceof MonitorStmt) cantAggr = true; } // Check for intervening side effects due to method calls if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { for (final ValueBox box : between.getUseBoxes()) { if (between == use && box == useBox) { // Reached use point, stop looking for // side effects break; } Value v = box.getValue(); if (v instanceof InvokeExpr || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) { cantAggr = true; break; } } } } // we give up: can't aggregate. if (cantAggr) { continue; } /* assuming that the d-u chains are correct, */ /* we need not check the actual contents of ld */ Value aggregatee = s.getRightOp(); if (usepair.valueBox.canContainValue(aggregatee)) { boolean wasSimpleCopy = isSimpleCopy(usepair.unit); usepair.valueBox.setValue(aggregatee); units.remove(s); hadAggregation = true; // clean up the tags. If s was not a simple copy, the new statement should get // the tags of s. // OK, this fix was wrong. The condition should not be // "If s was not a simple copy", but rather "If usepair.unit // was a simple copy". This way, when there's a load of a constant // followed by an invoke, the invoke gets the tags. if (wasSimpleCopy) { // usepair.unit.removeAllTags(); usepair.unit.addAllTagsOf(s); } } else { /* if(Options.v().verbose()) { G.v().out.println("[debug] failed aggregation"); G.v().out.println("[debug] tried to put "+aggregatee+ " into "+usepair.stmt + ": in particular, "+usepair.valueBox); G.v().out.println("[debug] aggregatee instanceof Expr: " +(aggregatee instanceof Expr)); }*/ } } return hadAggregation; }
public void flushCache() { super.flushCache(); canCompleteNormally_computed = false; }