/** * Utility method used in the construction of {@link UnitGraph}s, to be called only after the * unitToPreds and unitToSuccs maps have been built. * * <p><code>UnitGraph</code> provides an implementation of <code>buildHeadsAndTails()</code> which * defines the graph's set of heads to include the first {@link Unit} in the graph's body, * together with any other <tt>Unit</tt> which has no predecessors. It defines the graph's set of * tails to include all <tt>Unit</tt>s with no successors. Subclasses of <code>UnitGraph</code> * may override this method to change the criteria for classifying a node as a head or tail. */ protected void buildHeadsAndTails() { List tailList = new ArrayList(); List headList = new ArrayList(); for (Iterator unitIt = unitChain.iterator(); unitIt.hasNext(); ) { Unit s = (Unit) unitIt.next(); List succs = (List) unitToSuccs.get(s); if (succs.size() == 0) { tailList.add(s); } List preds = (List) unitToPreds.get(s); if (preds.size() == 0) { headList.add(s); } } // Add the first Unit, even if it is the target of // a branch. Unit entryPoint = (Unit) unitChain.getFirst(); if (!headList.contains(entryPoint)) { headList.add(entryPoint); } tails = Collections.unmodifiableList(tailList); heads = Collections.unmodifiableList(headList); }
/** * Constructs a <code>ThrowableSet</code> which contains the exception types represented in <code> * include</code>, except for those which are also in <code>exclude</code>. The constructor is * private to ensure that the only way to get a new <code>ThrowableSet</code> is by adding * elements to or removing them from an existing set. * * @param include The set of {@link RefType} and {@link AnySubType} objects representing the types * to be included in the set. * @param exclude The set of {@link AnySubType} objects representing the types to be excluded from * the set. */ private ThrowableSet(Set include, Set exclude) { exceptionsIncluded = Collections.unmodifiableSet(include); exceptionsExcluded = Collections.unmodifiableSet(exclude); // We don't need to clone include and exclude to guarantee // immutability since ThrowableSet(Set,Set) is private to this // class, where it is only called (via // Manager.v().registerSetIfNew()) with arguments which the // callers do not subsequently modify. }
@Override public List<Unit> getPredsOf(Unit unit) { if (unit.equals(nIf)) { return Collections.emptyList(); } else if (unit.equals(n1)) { return Collections.singletonList(nIf); } else if (unit.equals(n2)) { return Collections.singletonList(nIf); } else { throw new RuntimeException("UNEXPECTED CASE"); } }
/** A package-private method to provide unit tests with access to ThrowableSet's internals. */ Map getMemoizedAdds() { if (memoizedAdds == null) { return Collections.EMPTY_MAP; } else { return Collections.unmodifiableMap(memoizedAdds); } }
public Map<Unit, Set<TaintFact>> initialSeeds() { if (DEBUG) System.out.println("initial seeds"); return DefaultSeeds.make( Collections.singleton( Scene.v().getEntryPoints().get(0).getActiveBody().getUnits().getFirst()), zeroValue()); }
@Override public final List<Unit> getSuccsOf(Unit s) { if (this.forwardEdges.containsKey(s)) { return new ArrayList<>(this.forwardEdges.get(s)); } else { return Collections.emptyList(); } }
/** * Utility method that replaces the values of a {@link Map}, which must be instances of {@link * List}, with unmodifiable equivalents. * * @param map The map whose values are to be made unmodifiable. */ protected static void makeMappedListsUnmodifiable(Map map) { for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); List value = (List) entry.getValue(); if (value.size() == 0) { entry.setValue(Collections.EMPTY_LIST); } else { entry.setValue(Collections.unmodifiableList(value)); } } }
/** * Computes the analysis given a UnitGraph computed from a method body. It is recommended that a * ExceptionalUnitGraph (or similar) be provided for correct results in the case of exceptional * control flow. * * @param g a graph on which to compute the analysis. * @see ExceptionalUnitGraph */ public SimpleLiveLocals(UnitGraph graph) { if (Options.v().time()) Timers.v().liveTimer.start(); if (Options.v().verbose()) G.v() .out .println( "[" + graph.getBody().getMethod().getName() + "] Constructing SimpleLiveLocals..."); SimpleLiveLocalsAnalysis analysis = new SimpleLiveLocalsAnalysis(graph); if (Options.v().time()) Timers.v().livePostTimer.start(); // Build unitToLocals map { unitToLocalsAfter = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); unitToLocalsBefore = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); Iterator unitIt = graph.iterator(); while (unitIt.hasNext()) { Unit s = (Unit) unitIt.next(); FlowSet set = (FlowSet) analysis.getFlowBefore(s); unitToLocalsBefore.put(s, Collections.unmodifiableList(set.toList())); set = (FlowSet) analysis.getFlowAfter(s); unitToLocalsAfter.put(s, Collections.unmodifiableList(set.toList())); } } if (Options.v().time()) Timers.v().livePostTimer.end(); if (Options.v().time()) Timers.v().liveTimer.end(); }
private ArrayList<AnnotationElem> getElements(Set<? extends AnnotationElement> set) { ArrayList<AnnotationElem> aelemList = new ArrayList<AnnotationElem>(); for (AnnotationElement ae : set) { // Debug.printDbg("element: ", ae.getName() ," ", ae.getValue() ," type: ", ae.getClass()); // Debug.printDbg("value type: ", ae.getValue().getValueType() ," class: ", // ae.getValue().getClass()); Debug.printDbg(" element type: ", ae.getValue().getClass()); List<AnnotationElem> eList = handleAnnotationElement(ae, Collections.singletonList(ae.getValue())); if (eList != null) aelemList.addAll(eList); } return aelemList; }
/** * Utility method that produces a new map from the {@link Unit}s of this graph's body to the union * of the values stored in the two argument {@link Map}s, used to combine the maps of exceptional * and unexceptional predecessors and successors into maps of all predecessors and successors. The * values stored in both argument maps must be {@link List}s of {@link Unit}s, which are assumed * not to contain any duplicate <tt>Unit</tt>s. * * @param mapA The first map to be combined. * @param mapB The second map to be combined. */ protected Map combineMapValues(Map mapA, Map mapB) { // The duplicate screen Map result = new HashMap(mapA.size() * 2 + 1, 0.7f); for (Iterator chainIt = unitChain.iterator(); chainIt.hasNext(); ) { Unit unit = (Unit) chainIt.next(); List listA = (List) mapA.get(unit); if (listA == null) { listA = Collections.EMPTY_LIST; } List listB = (List) mapB.get(unit); if (listB == null) { listB = Collections.EMPTY_LIST; } int resultSize = listA.size() + listB.size(); if (resultSize == 0) { result.put(unit, Collections.EMPTY_LIST); } else { List resultList = new ArrayList(resultSize); Iterator listIt = null; // As a minor optimization of the duplicate screening, // copy the longer list first. if (listA.size() >= listB.size()) { resultList.addAll(listA); listIt = listB.iterator(); } else { resultList.addAll(listB); listIt = listA.iterator(); } while (listIt.hasNext()) { Object element = listIt.next(); // It is possible for there to be both an exceptional // and an unexceptional edge connecting two Units // (though probably not in a class generated by // javac), so we need to screen for duplicates. On the // other hand, we expect most of these lists to have // only one or two elements, so it doesn't seem worth // the cost to build a Set to do the screening. if (!resultList.contains(element)) { resultList.add(element); } } result.put(unit, Collections.unmodifiableList(resultList)); } } return result; }
public Code(TypeVars tvars) { this.j = Jimple.v(); this.localX = j.newLocal("x", IntType.v()); this.localY = j.newLocal("y", IntType.v()); this.localZ = j.newLocal("z", IntType.v()); this.localO = j.newLocal("o", RefType.v("java.lang.Object")); this.localT = j.newLocal("t", RefType.v("TestClass")); this.localThis = j.newLocal("this", RefType.v("TestClass")); this.varX = Var.fromLocal(localX); this.varY = Var.fromLocal(localY); this.varZ = Var.fromLocal(localZ); this.varO = Var.fromLocal(localO); this.varT = Var.fromLocal(localT); this.varThis = Var.fromLocal(localThis); this.tvarX = tvars.testParam(varX, ""); this.tvarY = tvars.testParam(varY, ""); this.tvarZ = tvars.testParam(varZ, ""); this.tvarO = tvars.testParam(varO, ""); this.tvarT = tvars.testParam(varT, ""); this.tvarThis = tvars.testParam(varThis, ""); this.init = Environments.makeEmpty() .add(varX, tvarX) .add(varY, tvarY) .add(varZ, tvarZ) .add(varO, tvarO) .add(varT, tvarT) .add(varThis, tvarThis); this.testClass = makeFreshClass("TestClass"); Map<SootField, TypeDomain.Type<Level>> fieldMap = new HashMap<>(); this.testLowField_int = new SootField("testLowField", IntType.v(), 0); testClass.addField(this.testLowField_int); fieldMap.put(testLowField_int, TLOW); this.testHighField_int = new SootField("testHighField", IntType.v(), 0); testClass.addField(this.testHighField_int); fieldMap.put(testHighField_int, THIGH); this.testStaticDynField_int = new SootField("testStaticDynField", IntType.v(), Modifier.STATIC); testClass.addField(this.testStaticDynField_int); fieldMap.put(testStaticDynField_int, DYN); // freeze field map this.fields = new FieldTable<>(fieldMap); Map<SootMethod, Signature<Level>> sigMap = new HashMap<>(); Symbol.Param<LowHigh.Level> param_x = param(0); Symbol.Param<LowHigh.Level> param_y = param(1); // Method: // int testCallee() // with {} effect {} this.testCallee__int = new SootMethod("testCallee", Collections.emptyList(), IntType.v(), Modifier.ABSTRACT); this.testClass.addMethod(testCallee__int); sigMap.put( this.testCallee__int, makeSignature( this.testCallee__int.getParameterCount(), Stream.of(leS(Symbol.literal(PUB), ret())).collect(toList()), Effects.emptyEffect())); // Method: // int testCallee_int_int__int (int, int) // with {@param1 <= @ret, @param2 <= @ret} effect {} this.testCallee_int_int__int = new SootMethod( "testCallee", asList(IntType.v(), IntType.v()), IntType.v(), Modifier.ABSTRACT); this.testClass.addMethod(testCallee_int_int__int); Stream<SigConstraint<Level>> sigCstrs = Stream.of(leS(param_x, ret()), leS(param_y, ret())); sigMap.put( this.testCallee_int_int__int, makeSignature( this.testCallee_int_int__int.getParameterCount(), sigCstrs.collect(toList()), Effects.emptyEffect())); // Method: // int ignoreSnd(int, int) // with { @param1 <= @ret } effect {} this.ignoreSnd_int_int__int = new SootMethod( "ignoreSnd", asList(IntType.v(), IntType.v()), IntType.v(), Modifier.ABSTRACT); this.testClass.addMethod(ignoreSnd_int_int__int); sigCstrs = Stream.of(leS(param_x, ret()), leS(param_y, param_y)); sigMap.put( this.ignoreSnd_int_int__int, makeSignature( this.ignoreSnd_int_int__int.getParameterCount(), sigCstrs.collect(toList()), Effects.emptyEffect())); // Method: // int writeToLowReturn0(int) // with { @param0 <= LOW } effect { LOW } this.writeToLowReturn0_int__int = new SootMethod("writeToLow", singletonList(IntType.v()), IntType.v(), Modifier.ABSTRACT); this.testClass.addMethod(this.writeToLowReturn0_int__int); sigCstrs = Stream.of((leS(param_x, literal(TLOW))), leS(ret(), ret())); sigMap.put( this.writeToLowReturn0_int__int, makeSignature( this.writeToLowReturn0_int__int.getParameterCount(), sigCstrs.collect(toList()), Effects.makeEffects(TLOW))); // Method: // int ignore0Low1ReturnHigh(int, int) // with { @param1 <= LOW, HIGH <= ret } effect {} this.ignore0Low1ReturnHigh = new SootMethod( "ignore0Low1ReturnHigh", asList(IntType.v(), IntType.v()), IntType.v(), Modifier.ABSTRACT); this.testClass.addMethod(this.ignore0Low1ReturnHigh); sigCstrs = Stream.of(leS(param(1), literal(TLOW)), leS(literal(THIGH), ret())); sigMap.put( this.ignore0Low1ReturnHigh, makeSignature( this.ignore0Low1ReturnHigh.getParameterCount(), sigCstrs.collect(toList()), Effects.emptyEffect())); // freeze signatures this.signatures = makeTable(sigMap); }
@Override public List<Unit> getTails() { return Collections.singletonList(nIf); }
public TaintFact createZeroValue() { return new TaintFact( new JimpleLocal("<<zero>>", NullType.v()), Collections.<DefinitionStmt>emptySet()); }
/** * Converts method and method parameters annotations from Dexlib to Jimple * * @param h * @param method */ void handleMethodAnnotation(Host h, Method method) { Set<? extends Annotation> aSet = method.getAnnotations(); if (!(aSet == null || aSet.isEmpty())) { List<Tag> tags = handleAnnotation(aSet, null); if (tags != null) for (Tag t : tags) if (t != null) { h.addTag(t); Debug.printDbg("add method annotation: ", t); } } ArrayList<String> parameterNames = new ArrayList<String>(); boolean addParameterNames = false; for (MethodParameter p : method.getParameters()) { String name = p.getName(); parameterNames.add(name); if (name != null) addParameterNames = true; } if (addParameterNames) { h.addTag(new ParamNamesTag(parameterNames)); } // Is there any parameter annotation? boolean doParam = false; List<? extends MethodParameter> parameters = method.getParameters(); for (MethodParameter p : parameters) { Debug.printDbg("parameter ", p, " annotations: ", p.getAnnotations()); if (p.getAnnotations().size() > 0) { doParam = true; break; } } if (doParam) { VisibilityParameterAnnotationTag tag = new VisibilityParameterAnnotationTag( parameters.size(), AnnotationConstants.RUNTIME_VISIBLE); for (MethodParameter p : parameters) { List<Tag> tags = handleAnnotation(p.getAnnotations(), null); // If we have no tag for this parameter, add a placeholder // so that we keep the order intact. if (tags == null) { tag.addVisibilityAnnotation(null); continue; } VisibilityAnnotationTag paramVat = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE); tag.addVisibilityAnnotation(paramVat); for (Tag t : tags) { if (t == null) continue; AnnotationTag vat = null; if (!(t instanceof VisibilityAnnotationTag)) { if (t instanceof DeprecatedTag) { vat = new AnnotationTag("Ljava/lang/Deprecated;"); } else if (t instanceof SignatureTag) { SignatureTag sig = (SignatureTag) t; ArrayList<AnnotationElem> sigElements = new ArrayList<AnnotationElem>(); for (String s : SootToDexUtils.splitSignature(sig.getSignature())) sigElements.add(new AnnotationStringElem(s, 's', "value")); AnnotationElem elem = new AnnotationArrayElem(sigElements, 's', "value"); vat = new AnnotationTag("Ldalvik/annotation/Signature;", Collections.singleton(elem)); } else { throw new RuntimeException( "error: unhandled tag for parameter annotation in method " + h + " (" + t + ")."); } } else { vat = ((VisibilityAnnotationTag) t).getAnnotations().get(0); } Debug.printDbg("add parameter annotation: ", t); paramVat.addAnnotation(vat); } } if (tag.getVisibilityAnnotations().size() > 0) h.addTag(tag); } }