private AssignStmt findFieldDef(Body b, FieldRef fr) { AssignStmt fdef = null; for (Unit u : b.getUnits()) { if (u instanceof AssignStmt) { AssignStmt fass = (AssignStmt) u; Value l = fass.getLeftOp(); if (l instanceof FieldRef) { FieldRef ffr = (FieldRef) l; if (ffr.getField().getSignature().toString() .equals(fr.getField().getSignature())) { fdef = fass; break; } } } } return fdef; }
void handleAssign(DefinitionStmt stmt) { Value lval = stmt.getLeftOp(); Value rval = stmt.getRightOp(); Variable rvar; if (lval instanceof Local) { rvar = getLocalVariable((Local)lval); } else { rvar = jt.makeVariable(rval); } et.translateExpr(rvar, stmt.getRightOpBox()); if (lval instanceof ArrayRef) { notSupported("We do not support arrays"); } else if (lval instanceof FieldRef) { notSupported("We do not support field references"); } }
private void printFieldRef(FieldRef v) { String refTypeName = v.getClass().getSimpleName(); p.openBlock(); String oldName = varName; SootField f = v.getField(); ttp.setVariableName("type"); f.getType().apply(ttp); p.print("SootFieldRef fieldRef = "); p.printNoIndent("Scene.v().makeFieldRef("); String className = f.getDeclaringClass().getName(); p.printNoIndent("Scene.v().getSootClass(\""+className+"\"),"); p.printNoIndent("\""+f.getName()+"\","); p.printNoIndent("type,"); p.printNoIndent(f.isStatic()+");"); p.println("Value "+oldName+" = Jimple.v().new"+refTypeName+"(fieldRef);"); varName = oldName; p.closeBlock(); }
private boolean isObjectArray(Value v, Body body) { for (Unit u : body.getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() == v) { if (assign.getRightOp() instanceof NewArrayExpr) { NewArrayExpr nea = (NewArrayExpr) assign.getRightOp(); if (isObject(nea.getBaseType())) return true; } else if (assign.getRightOp() instanceof FieldRef) { FieldRef fr = (FieldRef) assign.getRightOp(); if (fr.getType() instanceof ArrayType) if (isObject(((ArrayType) fr.getType()) .getArrayElementType())) return true; } } } } return false; }
private SootMethod getOrCreateInitializer(SootClass sc, Set<SootField> alreadyInitialized) { SootMethod smInit; // Create a static initializer if we don't already have one smInit = sc.getMethodByNameUnsafe("<clinit>"); if (smInit == null) { smInit = new SootMethod("<clinit>", Collections.<Type>emptyList(), VoidType.v()); smInit.setActiveBody(Jimple.v().newBody(smInit)); sc.addMethod(smInit); smInit.setModifiers(Modifier.PUBLIC | Modifier.STATIC); } else { smInit.retrieveActiveBody(); // We need to collect those variables that are already initialized somewhere for (Unit u : smInit.getActiveBody().getUnits()) { Stmt s = (Stmt) u; for (ValueBox vb : s.getDefBoxes()) if (vb.getValue() instanceof FieldRef) alreadyInitialized.add(((FieldRef) vb.getValue()).getField()); } } return smInit; }
private void checkAccessStmt(Stmt sootStmt, SootMethod currentMethod) { if(sootStmt.containsFieldRef()) { SootField accessField = sootStmt.getFieldRef().getField(); boolean isWrite = (((DefinitionStmt)sootStmt).getLeftOp() instanceof FieldRef); boolean isStatic = (sootStmt.getFieldRef() instanceof StaticFieldRef); Value object = isStatic ? NullConstant.v() : ((InstanceFieldRef)sootStmt.getFieldRef()).getBase(); String methodSig = currentMethod.getSignature(); List<Value> currentLocks = new ArrayList<Value>(lockStack); System.out.println(isWrite+" access on "+isStatic+" field "+accessField+" of "+object+" in "+methodSig+" with "+currentLocks.size()+" locks"); if(!variableAccesses.containsKey(methodSig)) { variableAccesses.put(methodSig, new HashSet<VariableAccess>()); } variableAccesses.get(currentMethod.getSignature()).add( new VariableAccess(accessField, sootStmt, currentMethod, isWrite, isStatic, currentLocks)); } }
private boolean checkSharedField(FieldRef ref, Expression field) { if (!Options.v().useSoundThreads()) { return false; } else { if (!this.stmtSwitch.isInMonitor()) { if (MhpInfo.v().getSharedFields(this.procInfo.getSootMethod()) .contains(ref.getField())) { // if the field can be modified in another thread, add a // havoc statement before it is used. return true; } else { // do nothing } } else { Log.info("Was in monitor ... "); } } return false; }
private boolean containsSameField(ValueM u, ValueM v) { Value uValue; Value vValue; SootField uField; SootField vField; analyzeMethod(u.getMethod()); analyzeMethod(v.getMethod()); uValue=localAssigns.get(u); vValue=localAssigns.get(v); if (uValue == null || vValue == null || !(uValue instanceof FieldRef) || !(vValue instanceof FieldRef)) return false; uField=((FieldRef)uValue).getField(); vField=((FieldRef)vValue).getField(); return uField.getSignature().equals(vField.getSignature()); }
private String findUriDef(Body b, Unit u, Local l) { final UnitGraph g = new ExceptionalUnitGraph(b); final SmartLocalDefs localDefs = new SmartLocalDefs(g, new SimpleLiveLocals(g)); final SimpleLocalUses localUses = new SimpleLocalUses(g, localDefs); List<Unit> defs = localDefs.getDefsOfAt((Local) l, u); if (defs.size() == 0) { System.out.println("warning: uri def empty!"); return null; } Unit def = defs.get(0); logger.debug("uri def: " + def); if (def instanceof IdentityStmt) { System.out.println("warning: do not handle uri from identity stmt"); return null; } else if (def instanceof AssignStmt) { AssignStmt ass = (AssignStmt) def; Value r = ass.getRightOp(); if (r instanceof FieldRef) { FieldRef fr = (FieldRef) r; SootField sf = fr.getField(); if (sf.getName().contains("URI")) { String auth = getFieldFromClass(sf); return auth; } } else { System.out.println("warning: uri: do not handle def '" + def + "'"); return null; } } return null; }
/** * Computes the global non-flow-sensitive alias information for the given * method * @param method The method for which to compute the alias information */ private Map<AccessPath, Set<AccessPath>> computeGlobalAliases(SootMethod method) { Map<AccessPath, Set<AccessPath>> res = new HashMap<AccessPath, Set<AccessPath>>(); // Find the aliases for (Unit u : method.getActiveBody().getUnits()) { if (!(u instanceof AssignStmt)) continue; final AssignStmt assign = (AssignStmt) u; // Aliases can only be generated on the heap if (!(assign.getLeftOp() instanceof FieldRef && (assign.getRightOp() instanceof FieldRef || assign.getRightOp() instanceof Local))) if (!(assign.getRightOp() instanceof FieldRef && (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof Local))) continue; final AccessPath apLeft = new AccessPath(assign.getLeftOp(), true); final AccessPath apRight = new AccessPath(assign.getRightOp(), true); Set<AccessPath> mapLeft = res.get(apLeft); if (mapLeft == null) { mapLeft = new HashSet<AccessPath>(); res.put(apLeft, mapLeft); } mapLeft.add(apRight); Set<AccessPath> mapRight = res.get(apRight); if (mapRight == null) { mapRight = new HashSet<AccessPath>(); res.put(apRight, mapRight); } mapLeft.add(apLeft); } return res; }
public static Value getFieldRefWrap(Value value) { if (value instanceof FieldRef) { return new EquivalentValue((FieldRef) value); } else { return value; } }
private void handleFieldRef(FieldRef fieldRef, AnalysisInfo out) { if(fieldRef instanceof InstanceFieldRef) { InstanceFieldRef instanceFieldRef = (InstanceFieldRef) fieldRef; //here we know that the receiver must point to an object Value base = instanceFieldRef.getBase(); out.put(base,NON_NULL); } //but the referenced object might point to everything // out.put(fieldRef, TOP); }
private void handleFieldRef(FieldRef fieldRef, AnalysisInfo out) { if(fieldRef instanceof InstanceFieldRef) { InstanceFieldRef instanceFieldRef = (InstanceFieldRef) fieldRef; //here we know that the receiver must point to an object Value base = instanceFieldRef.getBase(); out.put(base,NON_NULL); } }
private Value wrapValue(Value value) { if(value instanceof EquivalentValue) { return value; } else if(value instanceof FieldRef) { return new EquivalentValue(value); } else { return value; } }
public void inDefinitionStmt(DefinitionStmt s){ Value leftOp = s.getLeftOp(); if(leftOp instanceof FieldRef){ //System.out.println("leftOp is a fieldRef:"+s); SootField field = ((FieldRef)leftOp).getField(); //check if this is a final field if(field.isFinal()){ //System.out.println("the field is a final variable"); finalFieldDefined=true; } } }
private void convertGetFieldInsn(FieldInsnNode insn) { StackFrame frame = getFrame(insn); Operand[] out = frame.out(); Operand opr; Type type; if (out == null) { SootClass declClass = Scene.v().getSootClass( AsmUtil.toQualifiedName(insn.owner)); type = AsmUtil.toJimpleType(insn.desc); Value val; SootFieldRef ref; if (insn.getOpcode() == GETSTATIC) { ref = Scene.v().makeFieldRef(declClass, insn.name, type, true); val = Jimple.v().newStaticFieldRef(ref); } else { Operand base = popLocal(); ref = Scene.v().makeFieldRef(declClass, insn.name, type, false); InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef( base.stackOrValue(), ref); val = ifr; base.addBox(ifr.getBaseBox()); frame.in(base); frame.boxes(ifr.getBaseBox()); } opr = new Operand(insn, val); frame.out(opr); } else { opr = out[0]; type = opr.<FieldRef>value().getFieldRef().type(); if (insn.getOpcode() == GETFIELD) frame.mergeIn(pop()); } push(type, opr); }
private void checkFieldAnnotations(Expression expr, FieldRef fr) { LinkedList<SootAnnotations.Annotation> annot = SootAnnotations .parseFieldTags(fr.getField()); if (annot.contains(SootAnnotations.Annotation.NonNull)) { this.stmtSwitch.addStatement(this.stmtSwitch.getErrorModel() .createAssumeNonNull(expr)); } }
public static boolean isStaticGet(JAssignStmt a){ if(a.containsFieldRef()) { FieldRef fr = a.getFieldRef(); ValueBox vb = a.rightBox; Value v = vb.getValue(); if(fr.getField().isStatic()) { if(vb.getValue().toString().equals(fr.toString())){ return true; } } } return false; }
public static boolean isStaticPut(JAssignStmt a){ if (a.containsFieldRef()) { FieldRef fr = a.getFieldRef(); ValueBox vb = a.leftBox; Value v = vb.getValue(); if (fr.getField().isStatic()) if (vb.getValue().toString().equals(fr.toString())) return true; } return false; }
public static boolean isFieldLoad(JAssignStmt a){ Value right = a.rightBox.getValue(); if(a.containsFieldRef()){ FieldRef fr = a.getFieldRef(); if(right.toString().equals(fr.toString())) return true; } return false; }
public static boolean isFieldStore(JAssignStmt a){ Value left = a.leftBox.getValue(); if(a.containsFieldRef()){ FieldRef fr = a.getFieldRef(); if(left.toString().equals(fr.toString())) return true; } return false; }
private void replaceSootField(SootClass sc, Body b, AssignStmt aStmt, SootField sf) { SootClass sfClass = sf.getDeclaringClass(); LocalGenerator lg = new LocalGenerator(b); Local sfLocal = lg.generateLocal(sc.getType()); Unit sfLocalAssignU = Jimple.v().newAssignStmt( sfLocal, Jimple.v().newStaticFieldRef(sc.getField("instance", sc.getType()).makeRef())); Local sfLocal2 = lg.generateLocal(sfClass.getType()); Unit sfLocalAssignU2 = Jimple.v().newAssignStmt( sfLocal2, Jimple.v().newInstanceFieldRef(sfLocal, sc.getField(sfClass.getName(), sfClass.getType()).makeRef())); Unit assignU = null; if (aStmt.getLeftOp() instanceof FieldRef) { assignU = Jimple.v().newAssignStmt(Jimple.v().newInstanceFieldRef(sfLocal2, sf.makeRef()), aStmt.getRightOp()); } else { assignU = Jimple.v().newAssignStmt(aStmt.getLeftOp(), Jimple.v().newInstanceFieldRef(sfLocal2, sf.makeRef())); } b.getUnits().insertBefore(sfLocalAssignU, aStmt); b.getUnits().insertBefore(sfLocalAssignU2, aStmt); b.getUnits().insertBefore(assignU, aStmt); b.getUnits().remove(aStmt); System.out.println(b); }
/** * Determines whether a given value is a field ref or an array * @param val the value to inspect * @return true if fieldref/array */ public static boolean isFieldRefOrArrayRef(Value val){ if(val == null){ return false; } if(val instanceof FieldRef || val instanceof ArrayRef || (val instanceof Local && ((Local)val).getType() instanceof ArrayType)){ return true; } return false; }
/** * Analyses the field assignment if it corresponds to a registered rule. * @param ad context for current analysis. * @param st the statement analysed */ public void spyField(MethodSpyAnalysis ad, AssignStmt st) { Value left = st.getLeftOp(); if (left instanceof FieldRef) { SootField field = ((FieldRef) left).getField(); SpyField sf = field_tables.get(field); if (sf != null) sf.spy(ad, st); } }
/** * Method that handles the update of <em>security level</em> of a field, * more precisely, the level is not changed, however, it is checked whether * the assignment is possible. Therefore, the level of the field and the * level of the right hand side, which may be affected by the program * counter, will be considered. In addition, a <em>write effect</em> is * added and also checked, because an assignment to a field occurs. If the * field is static, also the class <em>write effects</em> of the class which * declares the field will be added and checked. Occurring exceptions are * logged. * * @param fieldRef * Field which is assigned and for which the * <em>security level</em> violations as well as the * <em>write effects</em> should be checked. */ private void handleFieldRef(FieldRef fieldRef) { ILevel leftLevel = getWeakestSecurityLevel(); ILevel rightLevel = takePCintoAccount(level); SootField sootField = fieldRef.getField(); String fieldSignature = getSignatureOfField(sootField); FieldEnvironment field = getStore().getFieldEnvironment(sootField); leftLevel = field.getLevel(); // SIDE-EFFECTS: |-----> addWriteEffectCausedByAssign(leftLevel, sootField); // SIDE-EFFECTS: Check class write effects for static field if (field.isStatic()) { SootClass sootClass = field.getDeclaringSootClass(); for (ILevel effected : field.getClassWriteEffects()) { addWriteEffectCausedByClass(effected, sootClass); } } // <-----| SIDE-EFFECTS if (!isWeakerOrEqualLevel(rightLevel, leftLevel)) { logSecurity(getMsg("security.field.stronger_assign", getSignatureOfAnalyzedMethod(), getSourceLine(), rightLevel.getName(), fieldSignature, leftLevel.getName())); } }
/** * Finds the last assignment to the given local representing a resource ID * by searching upwards from the given statement * * @param stmt * The statement from which to look backwards * @param local * The variable for which to look for assignments * @return The last value assigned to the given variable */ private Integer findLastResIDAssignment(Stmt stmt, Local local, BiDiInterproceduralCFG<Unit, SootMethod> cfg, Set<Stmt> doneSet) { if (!doneSet.add(stmt)) return null; // If this is an assign statement, we need to check whether it changes // the variable we're looking for if (stmt instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt; if (assign.getLeftOp() == local) { // ok, now find the new value from the right side if (assign.getRightOp() instanceof IntConstant) return ((IntConstant) assign.getRightOp()).value; else if (assign.getRightOp() instanceof FieldRef) { SootField field = ((FieldRef) assign.getRightOp()).getField(); for (Tag tag : field.getTags()) if (tag instanceof IntegerConstantValueTag) return ((IntegerConstantValueTag) tag).getIntValue(); else System.err.println("Constant " + field + " was of unexpected type"); } else if (assign.getRightOp() instanceof InvokeExpr) { InvokeExpr inv = (InvokeExpr) assign.getRightOp(); if (inv.getMethod().getName().equals("getIdentifier") && inv.getMethod().getDeclaringClass().getName().equals("android.content.res.Resources") && this.resourcePackages != null) { // The right side of the assignment is a call into the // well-known // Android API method for resource handling if (inv.getArgCount() != 3) { System.err.println("Invalid parameter count for call to getIdentifier"); return null; } // Find the parameter values String resName = ""; String resID = ""; String packageName = ""; // In the trivial case, these values are constants if (inv.getArg(0) instanceof StringConstant) resName = ((StringConstant) inv.getArg(0)).value; if (inv.getArg(1) instanceof StringConstant) resID = ((StringConstant) inv.getArg(1)).value; if (inv.getArg(2) instanceof StringConstant) packageName = ((StringConstant) inv.getArg(2)).value; else if (inv.getArg(2) instanceof Local) packageName = findLastStringAssignment(stmt, (Local) inv.getArg(2), cfg); else { System.err.println("Unknown parameter type in call to getIdentifier"); return null; } // Find the resource ARSCFileParser.AbstractResource res = findResource(resName, resID, packageName); if (res != null) return res.getResourceID(); } } } } // Continue the search upwards for (Unit pred : cfg.getPredsOf(stmt)) { if (!(pred instanceof Stmt)) continue; Integer lastAssignment = findLastResIDAssignment((Stmt) pred, local, cfg, doneSet); if (lastAssignment != null) return lastAssignment; } return null; }
/** * Gets whether a value and an access path may potentially point to the same * runtime object * @param ap The access path * @param val The value * @return The access path that actually matched if the given value and * access path alias. In the simplest case, this is the given access path. * When using recursive access paths, it can however also be a base * expansion. If the given access path and value do not alias, null is * returned. */ public AccessPath mayAlias(AccessPath ap, Value val) { // What cannot be represented in an access path cannot alias if (!AccessPath.canContainValue(val)) return null; // Constants can never alias if (val instanceof Constant) return null; // For instance field references, the base must match if (val instanceof Local) if (ap.getPlainValue() != val) return null; // For array references, the base must match if (val instanceof ArrayRef) if (ap.getPlainValue() != ((ArrayRef) val).getBase()) return null; // For instance field references, the base local must match if (val instanceof InstanceFieldRef) { if (!ap.isLocal() && !ap.isInstanceFieldRef()) return null; if (((InstanceFieldRef) val).getBase() != ap.getPlainValue()) return null; } // If the value is a static field reference, the access path must be // static as well if (val instanceof StaticFieldRef) if (!ap.isStaticFieldRef()) return null; // If we have an interactive aliasing algorithm, we check that as well /* if (aliasingStrategy.isInteractive()) return aliasingStrategy.mayAlias(new AccessPath(val1, false), new AccessPath(val2, false)); */ // Get the field set from the value SootField[] fields = val instanceof FieldRef ? new SootField[] { ((FieldRef) val).getField() } : new SootField[0]; return getReferencedAPBase(ap, fields); }
/** * Checks whether the given method or one of its transitive callees has * side-effects or calls a sink method * @param method The method to check * @param runList A set to receive all methods that have already been * processed * @param cache The cache in which to store the results * @return True if the given method or one of its transitive callees has * side-effects or calls a sink method, otherwise false. */ private boolean hasSideEffectsOrCallsSink(SootMethod method, Set<SootMethod> runList) { // Without a body, we cannot say much if (!method.hasActiveBody()) return false; // Do we already have an entry? Boolean hasSideEffects = methodSideEffects.get(method); if (hasSideEffects != null) return hasSideEffects; Boolean hasSink = methodSinks.get(method); if (hasSink != null) return hasSink; // Do not process the same method twice if (!runList.add(method)) return false; // If this is an Android stub method that just throws a stub exception, // this will never happen in practice and can be removed if (methodIsAndroidStub(method)) { methodSideEffects.put(method, false); return false; } // Scan for references to this variable for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof ArrayRef) { methodSideEffects.put(method, true); return true; } } Stmt s = (Stmt) u; // If this method calls another method for which we have a taint // wrapper, we need to conservatively assume that the taint wrapper // can do anything if (taintWrapper != null && taintWrapper.supportsCallee(s)) { methodSideEffects.put(method, true); return true; } if (s.containsInvokeExpr()) { // If this method calls a sink, we need to keep it if (sourceSinkManager != null && sourceSinkManager.isSink((Stmt) u, icfg, null)) { methodSinks.put(method, true); return true; } // Check the callees for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(u); edgeIt.hasNext(); ) { Edge e = edgeIt.next(); if (hasSideEffectsOrCallsSink(e.getTgt().method(), runList)) return true; } } } // Variable is not read methodSideEffects.put(method, false); return false; }
/** * Checks whether the given method or one of its transitive callees has * side-effects or calls a sink method * @param method The method to check * @param runList A set to receive all methods that have already been * processed * @param cache The cache in which to store the results * @return True if the given method or one of its transitive callees has * side-effects or calls a sink method, otherwise false. */ private boolean hasSideEffectsOrReadsThis(SootMethod method, Set<SootMethod> runList) { // Without a body, we cannot say much if (!method.hasActiveBody()) return false; // Do we already have an entry? Boolean hasSideEffects = methodSideEffects.get(method); if (hasSideEffects != null) return hasSideEffects; // Do not process the same method twice if (!runList.add(method)) return false; // If this is an Android stub method that just throws a stub exception, // this will never happen in practice and can be removed if (methodIsAndroidStub(method)) { methodSideEffects.put(method, false); return false; } // Scan for references to this variable Local thisLocal = method.isStatic() ? null : method.getActiveBody().getThisLocal(); for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof ArrayRef) { methodSideEffects.put(method, true); return true; } } Stmt s = (Stmt) u; // If this statement uses the "this" local, we have to // conservatively assume that is can read data if (thisLocal != null) for (ValueBox vb : s.getUseBoxes()) if (vb.getValue() == thisLocal) return true; if (s.containsInvokeExpr()) { // Check the callees for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(u); edgeIt.hasNext(); ) { Edge e = edgeIt.next(); if (hasSideEffectsOrReadsThis(e.getTgt().method(), runList)) return true; } } } // Variable is not read methodSideEffects.put(method, false); return false; }
/** * Computes the set of {@link EquivalentValue}s of all field references that are used * in this method but not set by the method or any method transitively called by this method. */ private Set<Value> trackableFields() { Set<Value> usedFieldRefs = new HashSet<Value>(); //add all field references that are in use boxes for (Unit unit : this.graph) { Stmt s = (Stmt) unit; List<ValueBox> useBoxes = s.getUseBoxes(); for (ValueBox useBox : useBoxes) { Value val = useBox.getValue(); if(val instanceof FieldRef) { FieldRef fieldRef = (FieldRef) val; if(fieldRef.getType() instanceof RefLikeType) usedFieldRefs.add(new EquivalentValue(fieldRef)); } } } //prune all fields that are written to if(!usedFieldRefs.isEmpty()) { if(!Scene.v().hasCallGraph()) { throw new IllegalStateException("No call graph found!"); } CallGraph cg = Scene.v().getCallGraph(); ReachableMethods reachableMethods = new ReachableMethods(cg,Collections.<MethodOrMethodContext>singletonList(container)); reachableMethods.update(); for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext();) { SootMethod m = (SootMethod) iterator.next(); if(m.hasActiveBody() && //exclude static initializer of same class (assume that it has already been executed) !(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) { for (Unit u : m.getActiveBody().getUnits()) { List<ValueBox> defBoxes = u.getDefBoxes(); for (ValueBox defBox : defBoxes) { Value value = defBox.getValue(); if(value instanceof FieldRef) { usedFieldRefs.remove(new EquivalentValue(value)); } } } } } } return usedFieldRefs; }
protected void internalTransform(final Body body, String phaseName, @SuppressWarnings("rawtypes") Map options) { //final ExceptionalUnitGraph g = new ExceptionalUnitGraph(body); //final SmartLocalDefs localDefs = new SmartLocalDefs(g, new SimpleLiveLocals(g)); //final SimpleLocalUses localUses = new SimpleLocalUses(g, localDefs); for (Unit u: getRefCandidates(body)) { Stmt s = (Stmt)u; boolean hasField = false; FieldRef fr = null; SootField sf = null; if (s.containsFieldRef()) { fr = s.getFieldRef(); sf = fr.getField(); if (sf != null) { hasField = true; } } else { throw new RuntimeException("Unit '"+ u +"' does not contain array ref nor field ref."); } if (!hasField) { Debug.printDbg("field ", fr ," '", fr ,"' has not been found!"); System.out.println("Warning: add missing field '"+ fr +"' to class!"); SootClass sc = null; String frStr = fr.toString(); if (frStr.contains(".<")) { sc = Scene.v().getSootClass(frStr.split(".<")[1].split(" ")[0].split(":")[0]); } else { sc = Scene.v().getSootClass(frStr.split(":")[0].replaceAll("^<", "")); } String fname = fr.toString().split(">")[0].split(" ")[2]; int modifiers = soot.Modifier.PUBLIC; Type ftype = fr.getType(); Debug.printDbg("missing field: to class '", sc ,"' field name '", fname ,"' field modifiers '", modifiers ,"' field type '", ftype ,"'"); sc.addField(new SootField(fname, ftype, modifiers)); } else { //System.out.println("field "+ sf.getName() +" '"+ sf +"' phantom: "+ isPhantom +" declared: "+ isDeclared); } } // for if statements }
@Override protected void internalTransform(Body body, String phaseName, Map<String, String> options) { ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body, DalvikThrowAnalysis.v(), true); LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(graph); LocalUses localUses = null; LocalCreation localCreation = null; // If a return statement's operand has only one definition and this is // a copy statement, we take the original operand for (Unit u : body.getUnits()) if (u instanceof ReturnStmt) { ReturnStmt retStmt = (ReturnStmt) u; if (retStmt.getOp() instanceof Local) { List<Unit> defs = localDefs.getDefsOfAt((Local) retStmt.getOp(), retStmt); if (defs.size() == 1 && defs.get(0) instanceof AssignStmt) { AssignStmt assign = (AssignStmt) defs.get(0); final Value rightOp = assign.getRightOp(); final Value leftOp = assign.getLeftOp(); // Copy over the left side if it is a local if (rightOp instanceof Local) { // We must make sure that the definition we propagate to // the return statement is not overwritten in between // a = 1; b = a; a = 3; return b; may not be translated // to return a; if (!isRedefined((Local) rightOp, u, assign, graph)) retStmt.setOp(rightOp); } else if (rightOp instanceof Constant) { retStmt.setOp(rightOp); } // If this is a field access which has no other uses, // we rename the local to help splitting else if (rightOp instanceof FieldRef) { if (localUses == null) localUses = LocalUses.Factory.newLocalUses(body, localDefs); if (localUses.getUsesOf(assign).size() == 1) { if (localCreation == null) localCreation = new LocalCreation(body.getLocals(), "ret"); Local newLocal = localCreation.newLocal(leftOp.getType()); assign.setLeftOp(newLocal); retStmt.setOp(newLocal); } } } } } }
private Object isANotTopConstantInInputSet(CPFlowSet set, Value toCheck) { if (toCheck instanceof Local || toCheck instanceof FieldRef) { String toCheckClassName = null; if (toCheck instanceof Local) toCheckClassName = localClassName; else toCheckClassName = ((FieldRef) toCheck).getField().getDeclaringClass().getName(); for (CPTuple tempTuple : set) { // check that the classNames are the same if (!(tempTuple.getSootClassName().equals(toCheckClassName))) { // classNames are not the same no point in continuing with // checks continue; } boolean tupleFound = false; if (tempTuple.containsLocal() && toCheck instanceof Local) { // check they are the same Local Local tempLocal = tempTuple.getVariable().getLocal(); if (tempLocal.getName().equals(((Local) toCheck).getName())) { // the set does have a constant value for this local tupleFound = true; } } else if (tempTuple.containsField() && toCheck instanceof FieldRef) { SootField toCheckField = ((FieldRef) toCheck).getField(); SootField tempField = tempTuple.getVariable().getSootField(); if (tempField.getName().equals(toCheckField.getName())) { // the set contains a constant value for this field tupleFound = true; } } if (tupleFound) { if (tempTuple.isTop()) return null; else return tempTuple.getValue(); } } } return null; }
private void convertPutFieldInsn(FieldInsnNode insn) { boolean instance = insn.getOpcode() == PUTFIELD; StackFrame frame = getFrame(insn); Operand[] out = frame.out(); Operand opr, rvalue; Type type; if (out == null) { SootClass declClass = Scene.v().getSootClass( AsmUtil.toQualifiedName(insn.owner)); type = AsmUtil.toJimpleType(insn.desc); Value val; SootFieldRef ref; rvalue = popImmediate(type); if (!instance) { ref = Scene.v().makeFieldRef(declClass, insn.name, type, true); val = Jimple.v().newStaticFieldRef(ref); frame.in(rvalue); } else { Operand base = popLocal(); ref = Scene.v().makeFieldRef(declClass, insn.name, type, false); InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef( base.stackOrValue(), ref); val = ifr; base.addBox(ifr.getBaseBox()); frame.in(rvalue, base); } opr = new Operand(insn, val); frame.out(opr); AssignStmt as = Jimple.v().newAssignStmt(val, rvalue.stackOrValue()); rvalue.addBox(as.getRightOpBox()); if (!instance) { frame.boxes(as.getRightOpBox()); } else { frame.boxes(as.getRightOpBox(), ((InstanceFieldRef) val).getBaseBox()); } setUnit(insn, as); } else { opr = out[0]; type = opr.<FieldRef>value().getFieldRef().type(); rvalue = pop(type); if (!instance) { /* PUTSTATIC only needs one operand on the stack, the rvalue */ frame.mergeIn(rvalue); } else { /* PUTFIELD has a rvalue and a base */ frame.mergeIn(rvalue, pop()); } } /* * in case any static field or array is read from, and the static constructor * or the field this instruction writes to, modifies that field, write out any * previous read from field/array */ assignReadOps(null); }
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; }
/** * Computes the global non-flow-sensitive alias information for the given * method * @param method The method for which to compute the alias information */ private void computeGlobalAliases(SootMethod method) { synchronized (globalAliases) { // If we already know the aliases for the given method, there is nothing // left to be done if (globalAliases.containsRow(method)) return; // Find the aliases for (Unit u : method.getActiveBody().getUnits()) { if (!(u instanceof AssignStmt)) continue; final AssignStmt assign = (AssignStmt) u; // Aliases can only be generated on the heap if (!(assign.getLeftOp() instanceof FieldRef && (assign.getRightOp() instanceof FieldRef || assign.getRightOp() instanceof Local))) if (!(assign.getRightOp() instanceof FieldRef && (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof Local))) continue; final AccessPath apLeft = new AccessPath(assign.getLeftOp()); final AccessPath apRight = new AccessPath(assign.getRightOp()); Set<AccessPath> mapLeft = globalAliases.get(method, apLeft); if (mapLeft == null) { mapLeft = new HashSet<AccessPath>(); globalAliases.put(method, apLeft, mapLeft); } mapLeft.add(apRight); Set<AccessPath> mapRight = globalAliases.get(method, apRight); if (mapRight == null) { mapRight = new HashSet<AccessPath>(); globalAliases.put(method, apRight, mapRight); } mapLeft.add(apLeft); } } }
/** * Method looks up the <em>security level</em> of the given field reference. * Therefore it checks whether the level at the field is valid and set this * <em>security level</em> to the calculated level * {@link SecurityLevelValueReadSwitch#level}. If the field is a library * field or the level is not valid the weakest available level is taken * instead. Occurring exceptions are logged. * * @param fieldRef * Field reference for which the <em>security level</em> should * be calculated. */ private void handleFieldAccess(FieldRef fieldRef) { SootField sootField = fieldRef.getField(); FieldEnvironment field = getStore().getFieldEnvironment(sootField); this.level = field.getLevel(); }