@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { //is the invokeExpr a source method? if(isSourceMethod(v)) { StringConstant newSourceValue = StringConstant.v("loggingPoint"); SMTBinding binding = stmtVisitor.createNewBindingForValue(newSourceValue); stmtVisitor.addValueBindingToVariableDeclaration(newSourceValue, binding); //no smt-statement required, just return the binding this.result = binding; // Additionally check whether the source method need special treatment if(isExpressionThatNeedsToBeConvertedToSMT(v)) { convertSpecialExpressionsToSMT(v, currentStatement); } } else { if(isStringOperationSupportedBySMT(v)) convertStringOperationToSMT(v, v.getBase()); else if(isExpressionThatNeedsToBeConvertedToSMT(v)) convertSpecialExpressionsToSMT(v, currentStatement); else convertAPIMethodToSMT(v); } }
private boolean isCallToSuper(SpecialInvokeExpr sie) { SootClass classWithInvokation = sie.getMethod().getDeclaringClass(); SootClass currentClass = stmtV.getBelongingClass(); while (currentClass.hasSuperclass()) { currentClass = currentClass.getSuperclass(); if (currentClass.equals(classWithInvokation)) { return true; } } // If we're dealing with phantom classes, we might not actually // arrive at java.lang.Object. In this case, we should not fail // the check if (currentClass.isPhantom() && !currentClass.getName().equals("java.lang.Object")) return true; return false; // we arrived at java.lang.Object and did not find a declaration }
/** Returns the target for the given SpecialInvokeExpr. */ public SootMethod resolveSpecialDispatch(SpecialInvokeExpr ie, SootMethod container) { container.getDeclaringClass().checkLevel(SootClass.HIERARCHY); SootMethod target = ie.getMethod(); target.getDeclaringClass().checkLevel(SootClass.HIERARCHY); /* This is a bizarre condition! Hopefully the implementation is correct. See VM Spec, 2nd Edition, Chapter 6, in the definition of invokespecial. */ if ("<init>".equals(target.getName()) || target.isPrivate()) return target; else if (isClassSubclassOf(target.getDeclaringClass(), container.getDeclaringClass())) return resolveConcreteDispatch(container.getDeclaringClass(), target); else return target; }
public void fill() { DomI domI = (DomI) doms[0]; DomM domM = (DomM) doms[1]; int numI = domI.size(); for (int iIdx = 0; iIdx < numI; iIdx++) { Unit i = (Unit) domI.get(iIdx); if(SootUtilities.isInvoke(i)){ InvokeExpr ie = SootUtilities.getInvokeExpr(i); if(ie instanceof SpecialInvokeExpr){ SootMethod m = ie.getMethod(); m = StubRewrite.maybeReplaceCallDest(SootUtilities.getMethod(i), m); int mIdx = domM.indexOf(m); if (mIdx >= 0) add(iIdx, mIdx); else if (Config.verbose >= 2) Messages.log(NOT_FOUND, m, SootUtilities.toLocStr(i)); } } } }
@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { logger.fine("Invoke expression is of type SpecialInvoke"); logger.finest(v.toString()); rightElement = RightElement.NOT; if (actualContext == StmtContext.INVOKE || actualContext == StmtContext.ASSIGNRIGHT ) { Local[] args = vh.getArgumentsForInvokedMethod(v); String method = v.getMethod().toString(); if (ExternalClasses.methodMap.containsKey(method)) { logger.fine("Found an external class " + method); logger.fine("This class is treated in a special way"); ExternalClasses.receiveCommand(method, callingStmt, args); } else { logger.fine("Found an external class " + method); logger.fine("This class is treated as an internal class"); JimpleInjector.storeArgumentLevels(callingStmt, args); } } else { throw new InternalAnalyzerException( "Unexpected Context for Invoke Expression"); } }
public void caseSpecialInvokeExpr(SpecialInvokeExpr expr) { // Constructor calls, maybe Variable bvar = st.getLocalVariable((Local)expr.getBase()); SootMethod m = expr.getMethod(); if (m.getName().equals("<init>")) { SootClass dc = m.getDeclaringClass(); if (isFoo(dc)) { FooInit fi = new FooInit(); fi.setAssignmentTarget(bvar); st.addStatement(fi); return; } } handleCall(expr, expr.getMethod()); }
private InvokeStmt getFirstSpecialInvoke(Body b){ for (Unit u : b.getUnits()) { Stmt s = (Stmt)u; if (!(s instanceof InvokeStmt)) continue; InvokeExpr invokeExpr = ((InvokeStmt)s).getInvokeExpr(); if (!(invokeExpr instanceof SpecialInvokeExpr)) continue; return (InvokeStmt)s; } // but there will always be either a call to this() or to super() // from the constructor return null; }
@Override public Set<SootMethod> load(Unit u) throws Exception { Stmt stmt = (Stmt)u; InvokeExpr ie = stmt.getInvokeExpr(); FastHierarchy fastHierarchy = Scene.v().getFastHierarchy(); //FIXME Handle Thread.start etc. if(ie instanceof InstanceInvokeExpr) { if(ie instanceof SpecialInvokeExpr) { //special return Collections.singleton(ie.getMethod()); } else { //virtual and interface InstanceInvokeExpr iie = (InstanceInvokeExpr) ie; Local base = (Local) iie.getBase(); RefType concreteType = bodyToLMNAA.getUnchecked(unitToOwner.get(u)).concreteType(base, stmt); if(concreteType!=null) { //the base variable definitely points to a single concrete type SootMethod singleTargetMethod = fastHierarchy.resolveConcreteDispatch(concreteType.getSootClass(), iie.getMethod()); return Collections.singleton(singleTargetMethod); } else { SootClass baseTypeClass; if(base.getType() instanceof RefType) { RefType refType = (RefType) base.getType(); baseTypeClass = refType.getSootClass(); } else if(base.getType() instanceof ArrayType) { baseTypeClass = Scene.v().getSootClass("java.lang.Object"); } else if(base.getType() instanceof NullType) { //if the base is definitely null then there is no call target return Collections.emptySet(); } else { throw new InternalError("Unexpected base type:"+base.getType()); } return fastHierarchy.resolveAbstractDispatch(baseTypeClass, iie.getMethod()); } } } else { //static return Collections.singleton(ie.getMethod()); } }
@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr sie) { BuilderMethodReference method = DexPrinter.toMethodReference (sie.getMethodRef(), dexFile); List<Register> arguments = getInstanceInvokeArgumentRegs(sie); if (isCallToConstructor(sie) || isCallToPrivate(sie)) { stmtV.addInsn(buildInvokeInsn("INVOKE_DIRECT", method, arguments), origStmt); } else if (isCallToSuper(sie)) { stmtV.addInsn(buildInvokeInsn("INVOKE_SUPER", method, arguments), origStmt); } else { // This should normally never happen, but if we have such a // broken call (happens in malware for instance), we fix it. stmtV.addInsn(buildInvokeInsn("INVOKE_VIRTUAL", method, arguments), origStmt); } }
/** Returns the target for the given SpecialInvokeExpr. */ public SootMethod resolveSpecialDispatch(SpecialInvokeExpr ie, SootMethod container) { SootMethod target = ie.getMethod(); /* This is a bizarre condition! Hopefully the implementation is correct. See VM Spec, 2nd Edition, Chapter 6, in the definition of invokespecial. */ if (target.getName().equals("<init>") || target.isPrivate()) return target; else if (isSubclass(target.getDeclaringClass(), container.getDeclaringClass())) return resolveConcreteDispatch(container.getDeclaringClass(), target ); else return target; }
@Override protected void transform(ValueBox invocationBox, SpecialInvokeExpr invocation, CompositeExpressionTransformer transforms) { // StringBuilder.<init>(...) -> new AugmentedStringBuilder.<init>(...) SootMethodRef newMethodRef = soot.Scene.v() .getSootClass(getReplacementClass().getName()) .getMethod("<init>", invocation.getArgs().stream().map(Value::getType).collect(Collectors.toList())) .makeRef(); invocation.setMethodRef(newMethodRef); // Add a one-time transform to handle instantiation, which is assumed to immediately follow this statement transforms.add(new OneTimeTransform(new InstantiationTransformer(getTargetClass(), getReplacementClass()))); }
private static void initializePeP(SootClass sc){ SootMethod onCreate = null; log.info("add Pep initialization in class "+ sc); for(SootMethod sm : sc.getMethods()){ if(sm.getName().equals("onCreate") && sm.getParameterCount() == 1 && sm.getParameterType(0).toString().equals("android.os.Bundle")){ onCreate = sm; } } if(onCreate != null){ List<Unit> generated = new ArrayList<Unit>(); Body body = onCreate.retrieveActiveBody(); Local thisLocal = body.getThisLocal(); SootClass context = Scene.v().forceResolve("android.content.Context", SootClass.BODIES); // SootMethod applicationContext =sc.getMethod("android.content.Context getApplicationContext()"); SootMethod applicationContext = context.getMethod("android.content.Context getApplicationContext()"); SpecialInvokeExpr virtInvExpr = Jimple.v().newSpecialInvokeExpr(thisLocal, applicationContext.makeRef()); Local applicationContextLocal = generateFreshLocal(body, RefType.v("android.content.Context")); generated.add(Jimple.v().newAssignStmt(applicationContextLocal, virtInvExpr)); List<Object> args = new ArrayList<Object>(); args.add(RefType.v("android.content.Context")); args.add(applicationContextLocal); StaticInvokeExpr staticInvExpr = Instrumentation.createJimpleStaticInvokeExpr(Settings.instance.INSTRUMENTATION_HELPER_JAVA, Settings.instance.INSTRUMENTATION_HELPER_INITIALIZE_METHOD, args); generated.add(Jimple.v().newInvokeStmt(staticInvExpr)); Unit onCreateSpecialInvoke = getSuperOnCreateUnit(body); if(onCreateSpecialInvoke == null) throw new RuntimeException("error: super.onCreate() statement missing in method "+ onCreate); body.getUnits().insertAfter(generated, onCreateSpecialInvoke); } }
@Override public Set<SootMethod> load(Unit u) throws Exception { Stmt stmt = (Stmt) u; InvokeExpr ie = stmt.getInvokeExpr(); FastHierarchy fastHierarchy = Scene.v().getFastHierarchy(); // FIXME Handle Thread.start etc. if (ie instanceof InstanceInvokeExpr) { if (ie instanceof SpecialInvokeExpr) { // special return Collections.singleton(ie.getMethod()); } else { // virtual and interface InstanceInvokeExpr iie = (InstanceInvokeExpr) ie; Local base = (Local) iie.getBase(); RefType concreteType = bodyToLMNAA.getUnchecked(unitToOwner.get(u)).concreteType(base, stmt); if (concreteType != null) { // the base variable definitely points to a // single concrete type SootMethod singleTargetMethod = fastHierarchy .resolveConcreteDispatch(concreteType.getSootClass(), iie.getMethod()); return Collections.singleton(singleTargetMethod); } else { SootClass baseTypeClass; if (base.getType() instanceof RefType) { RefType refType = (RefType) base.getType(); baseTypeClass = refType.getSootClass(); } else if (base.getType() instanceof ArrayType) { baseTypeClass = Scene.v().getSootClass("java.lang.Object"); } else if (base.getType() instanceof NullType) { // if the base is definitely null then there // is no call target return Collections.emptySet(); } else { throw new InternalError("Unexpected base type:" + base.getType()); } return fastHierarchy.resolveAbstractDispatch(baseTypeClass, iie.getMethod()); } } } else { // static return Collections.singleton(ie.getMethod()); } }
public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { printInvokeExpr(v); }
/** * Creates a method body that throws an "unresolved compilation error" * message * @param declaringClass The class that was supposed to contain the method * @return The created SootMethod */ private SootMethod createUnresolvedErrorMethod(SootClass declaringClass) { SootMethod m = new SootMethod(name, parameterTypes, returnType, isStatic()?Modifier.STATIC:0); int modifiers = Modifier.PUBLIC; // we don't know who will be calling us if (isStatic()) modifiers |= Modifier.STATIC; m.setModifiers(modifiers); JimpleBody body = Jimple.v().newBody(m); m.setActiveBody(body); final LocalGenerator lg = new LocalGenerator(body); // For producing valid Jimple code, we need to access all parameters. // Otherwise, methods like "getThisLocal()" will fail. if (!isStatic) { RefType thisType = RefType.v(declaringClass); Local lThis = lg.generateLocal(thisType); body.getUnits().add(Jimple.v().newIdentityStmt(lThis, Jimple.v().newThisRef(thisType))); } for (int i = 0; i < m.getParameterCount(); i++) { Type paramType = m.getParameterType(i); Local lParam = lg.generateLocal(paramType); body.getUnits().add(Jimple.v().newIdentityStmt(lParam, Jimple.v().newParameterRef(paramType, i))); } //exc = new Error RefType runtimeExceptionType = RefType.v("java.lang.Error"); NewExpr newExpr = Jimple.v().newNewExpr(runtimeExceptionType); Local exceptionLocal = lg.generateLocal(runtimeExceptionType); AssignStmt assignStmt = Jimple.v().newAssignStmt(exceptionLocal, newExpr); body.getUnits().add(assignStmt); //exc.<init>(message) SootMethodRef cref = Scene.v().makeConstructorRef(runtimeExceptionType.getSootClass(), Collections.<Type>singletonList(RefType.v("java.lang.String"))); SpecialInvokeExpr constructorInvokeExpr = Jimple.v().newSpecialInvokeExpr(exceptionLocal, cref, StringConstant.v("Unresolved compilation error: Method "+getSignature()+" does not exist!")); InvokeStmt initStmt = Jimple.v().newInvokeStmt(constructorInvokeExpr); body.getUnits().insertAfter(initStmt, assignStmt); //throw exc body.getUnits().insertAfter(Jimple.v().newThrowStmt(exceptionLocal), initStmt); declaringClass.addMethod(m); return m; }
private void split_new() { LocalDefs defs = LocalDefs.Factory.newLocalDefs(jb); PatchingChain<Unit> units = this.jb.getUnits(); Stmt[] stmts = new Stmt[units.size()]; units.toArray(stmts); for ( Stmt stmt : stmts ) { if ( stmt instanceof InvokeStmt ) { InvokeStmt invoke = (InvokeStmt)stmt; if ( invoke.getInvokeExpr() instanceof SpecialInvokeExpr ) { SpecialInvokeExpr special = (SpecialInvokeExpr)invoke.getInvokeExpr(); if ( special.getMethodRef().name().equals("<init>") ) { List<Unit> deflist = defs.getDefsOfAt( (Local)special.getBase(), invoke); while ( deflist.size() == 1 ) { Stmt stmt2 = (Stmt)deflist.get(0); if ( stmt2 instanceof AssignStmt ) { AssignStmt assign = (AssignStmt)stmt2; if ( assign.getRightOp() instanceof Local ) { deflist = defs.getDefsOfAt( (Local)assign.getRightOp(), assign); continue; } else if ( assign.getRightOp() instanceof NewExpr ) { Local newlocal = Jimple.v().newLocal( "tmp", null); newlocal.setName("tmp$" + System.identityHashCode(newlocal)); this.jb.getLocals().add(newlocal); special.setBase(newlocal); DefinitionStmt assignStmt = Jimple.v().newAssignStmt( assign.getLeftOp(), newlocal); Unit u = Util.findLastIdentityUnit(jb, assign); units.insertAfter(assignStmt, u); assign.setLeftOp(newlocal); this.addLocal(newlocal); this.initAssignment(assignStmt); } } break; } } } } } }
private void split_new() { LocalDefs defs = LocalDefs.Factory.newLocalDefs(stmtBody); PatchingChain<Unit> units = stmtBody.getUnits(); Stmt[] stmts = new Stmt[units.size()]; units.toArray(stmts); for (Stmt stmt : stmts) { if(stmt instanceof InvokeStmt) { InvokeStmt invoke = (InvokeStmt) stmt; if(invoke.getInvokeExpr() instanceof SpecialInvokeExpr) { SpecialInvokeExpr special = (SpecialInvokeExpr) invoke.getInvokeExpr(); if("<init>".equals(special.getMethodRef().name())) { List<Unit> deflist = defs.getDefsOfAt((Local) special.getBase(), invoke); while(deflist.size() == 1) { Stmt stmt2 = (Stmt) deflist.get(0); if(stmt2 instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt2; if(assign.getRightOp() instanceof Local) { deflist = defs.getDefsOfAt((Local) assign.getRightOp(), assign); continue; } else if(assign.getRightOp() instanceof NewExpr) { // We split the local. //G.v().out.println("split: [" + assign + "] and [" + stmt + "]"); Local newlocal = Jimple.v().newLocal("tmp", null); stmtBody.getLocals().add(newlocal); special.setBase(newlocal); units.insertAfter(Jimple.v().newAssignStmt(assign.getLeftOp(), newlocal), assign); assign.setLeftOp(newlocal); } } break; } } } } } }
private void split_new() { LocalDefs defs = LocalDefs.Factory.newLocalDefs(stmtBody); PatchingChain<Unit> units = stmtBody.getUnits(); Stmt[] stmts = new Stmt[units.size()]; units.toArray(stmts); for (Stmt stmt : stmts) { if(stmt instanceof InvokeStmt) { InvokeStmt invoke = (InvokeStmt) stmt; if(invoke.getInvokeExpr() instanceof SpecialInvokeExpr) { SpecialInvokeExpr special = (SpecialInvokeExpr) invoke.getInvokeExpr(); if(special.getMethodRef().name().equals("<init>")) { List<Unit> deflist = defs.getDefsOfAt((Local) special.getBase(), invoke); while(deflist.size() == 1) { Stmt stmt2 = (Stmt) deflist.get(0); if(stmt2 instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt2; if(assign.getRightOp() instanceof Local) { deflist = defs.getDefsOfAt((Local) assign.getRightOp(), assign); continue; } else if(assign.getRightOp() instanceof NewExpr) { // We split the local. //G.v().out.println("split: [" + assign + "] and [" + stmt + "]"); Local newlocal = Jimple.v().newLocal("tmp", null); stmtBody.getLocals().add(newlocal); special.setBase(newlocal); units.insertAfter(Jimple.v().newAssignStmt(assign.getLeftOp(), newlocal), assign); assign.setLeftOp(newlocal); } } break; } } } } } }
private boolean isCallToPrivate(SpecialInvokeExpr sie) { return sie.getMethod().isPrivate(); }
private boolean isCallToConstructor(SpecialInvokeExpr sie) { return sie.getMethod().isConstructor(); }
public void caseSpecialInvokeExpr(SpecialInvokeExpr expr) { caseInstanceInvokeExpr(expr); }
/** This method change all new Obj/<init>(args) pairs to new Obj(args) idioms. */ protected void internalTransform(Body b, String phaseName, Map options) { GrimpBody body = (GrimpBody)b; if(Options.v().verbose()) G.v().out.println("[" + body.getMethod().getName() + "] Folding constructors..."); Chain units = body.getUnits(); List<Unit> stmtList = new ArrayList<Unit>(); stmtList.addAll(units); Iterator<Unit> it = stmtList.iterator(); LocalUses localUses = LocalUses.Factory.newLocalUses(b); /* 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 */ Value lhs = ((AssignStmt)s).getLeftOp(); if (!(lhs instanceof Local)) continue; Value rhs = ((AssignStmt)s).getRightOp(); if (!(rhs instanceof NewExpr)) continue; /* TO BE IMPLEMENTED LATER: move any copy of the object reference for lhs down beyond the NewInvokeExpr, with the rationale being that you can't modify the object before the constructor call in any case. Also, do note that any new's (object creation) without corresponding constructors must be dead. */ 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; SpecialInvokeExpr oldInvoke = ((SpecialInvokeExpr)is.getInvokeExpr()); LinkedList invokeArgs = new LinkedList(); for (int i = 0; i < oldInvoke.getArgCount(); i++) invokeArgs.add(oldInvoke.getArg(i)); AssignStmt constructStmt = Grimp.v().newAssignStmt ((AssignStmt)s); constructStmt.setRightOp (Grimp.v().newNewInvokeExpr (((NewExpr)rhs).getBaseType(), oldInvoke.getMethodRef(), invokeArgs)); MadeNewInvokeExpr = true; use.redirectJumpsToThisTo(constructStmt); units.insertBefore(constructStmt, use); units.remove(use); } if (MadeNewInvokeExpr) { units.remove(s); } } }
private boolean checkThreadCreationStmt(Stmt sootStmt) { // Check 1: If the thread is created in a new Thread() constructor if(sootStmt.containsInvokeExpr()) { // Check if the current statement is a constructor if(sootStmt.getInvokeExpr() instanceof SpecialInvokeExpr) { // It's a constructor. SpecialInvokeExpr constructorExpr = (SpecialInvokeExpr)sootStmt.getInvokeExpr(); // The actual class being constructed String className = SusHelper.getClassFromSignature(constructorExpr.getMethod().getSignature()); try { // We're constructing a new Thread() or new Thread(Runnable) if(Thread.class.isAssignableFrom( Class.forName(className, false, this.getClass().getClassLoader()))) { String argumentClass = (constructorExpr.getArgCount() == 0) ? null : constructorExpr.getArg(0).getType().toString(); // We have something like new Thread(? extends Runnable) boolean runnableInvocation = (argumentClass != null) && (className.equals("java.lang.Thread")) && (java.lang.Runnable.class.isAssignableFrom( Class.forName(argumentClass, false, this.getClass().getClassLoader()))); // Thread constructed as new Thread(Runnable) if(runnableInvocation) { Type runnableType = innerRunnable.get(constructorExpr.getArg(0)); if(runnableType != null) { innerRunnable.put(constructorExpr.getBase(), runnableType); //System.out.println("Setting "+constructorExpr.getBase()+" as type: "+runnableType); return true; } } else if(!className.equals("java.lang.Thread")) { // It's a constructor statement. new <? extends Thread>. Now get the assignee innerRunnable.put(constructorExpr.getBase(), constructorExpr.getBase().getType()); //System.out.println("Setting "+constructorExpr.getBase()+" as type: "+constructorExpr.getBase().getType()); return true; } } // We're doing a new Runnable() now. Not thread creation yet. else if(java.lang.Runnable.class.isAssignableFrom( Class.forName(className, false, this.getClass().getClassLoader()))) { innerRunnable.put(constructorExpr.getBase(), constructorExpr.getBase().getType()); } } catch (Exception e) { e.printStackTrace(); } } } // Check 2: Newly constructed runnables are only assigned to a Runnable variable // after the constructor ends. Hence this is required. // Same for thread constructions else if (sootStmt instanceof DefinitionStmt) { // This section makes sure all variables that are assigned Runnable values are marked with the right type DefinitionStmt defStmt = (DefinitionStmt)sootStmt; if(innerRunnable.containsKey(defStmt.getRightOp())) { innerRunnable.put(defStmt.getLeftOp(), innerRunnable.get(defStmt.getRightOp())); //System.out.println("Setting "+defStmt.getLeftOp()+" as type: "+innerRunnable.get(defStmt.getRightOp())); } } return false; }
static private boolean specialCaseInvoke(SootStmtSwitch ss, Value lhs, InvokeExpr ivk) { SootValueSwitch valueswitch = ss.getValueSwitch(); ProgramFactory pf = GlobalsCache.v().getPf(); // java.lang.String.length is treated as a special case: resolveBaseIfNecessary(ivk); if (ivk.getMethod().getSignature() .contains("<java.lang.String: int length()>") && lhs != null) { if (ivk instanceof SpecialInvokeExpr) { ((SpecialInvokeExpr) ivk).getBase().apply(valueswitch); } else if (ivk instanceof VirtualInvokeExpr) { ((VirtualInvokeExpr) ivk).getBase().apply(valueswitch); } else { throw new RuntimeException("Bad usage of String.length?"); } Expression[] indices = { valueswitch.getExpression() }; Expression right = pf.mkArrayAccessExpression(pf.getIntType(), SootPrelude.v().getStringSizeHeapVariable(), indices); lhs.apply(valueswitch); Expression left = valueswitch.getExpression(); AssignmentTranslation.translateAssignment(ss, left, right); return true; } if (ivk.getMethod().getSignature() .contains("<java.lang.System: void exit(int)>")) { Log.debug("Surppressing false positive from call to System.exit"); // this is not a return statement, it actually ends the application. // ss.addStatement(pf.mkAssumeStatement(new // Attribute[]{pf.mkNoVerifyAttribute()}, // pf.mkBooleanLiteral(false))); ss.addStatement(pf.mkReturnStatement()); return true; } if (ivk.getMethod() .getSignature() .contains( "java.lang.Throwable: void addSuppressed(java.lang.Throwable)")) { ss.addStatement(TranslationHelpers.mkLocationAssertion( ss.getCurrentStatement(), true)); return true; } if (ivk.getMethod().getSignature().contains("addSuppressed")) { System.err.println(ivk.getMethod().getSignature()); } return false; }
@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr arg0) { throw new RuntimeException("This must be handeled by SootStmtSwitch!"); }
static private boolean specialCaseInvoke(SootStmtSwitch ss, Value lhs, InvokeExpr ivk) { SootValueSwitch valueswitch = ss.getValueSwitch(); ProgramFactory pf = GlobalsCache.v().getPf(); // java.lang.String.length is treated as a special case: if (ivk.getMethod().getSignature() .contains("<java.lang.String: int length()>") && lhs != null) { if (ivk instanceof SpecialInvokeExpr) { ((SpecialInvokeExpr) ivk).getBase().apply(valueswitch); } else if (ivk instanceof VirtualInvokeExpr) { ((VirtualInvokeExpr) ivk).getBase().apply(valueswitch); } else { throw new RuntimeException("Bad usage of String.length?"); } Expression[] indices = { valueswitch.getExpression() }; Expression right = pf.mkArrayAccessExpression(pf.getIntType(), SootPrelude.v().getStringSizeHeapVariable(), indices); lhs.apply(valueswitch); Expression left = valueswitch.getExpression(); AssignmentTranslation.translateAssignment(ss, left, right); return true; } if (ivk.getMethod().getSignature() .contains("<java.lang.System: void exit(int)>")) { Log.info("Surppressing false positive from call to System.exit"); // this is not a return statement, it actually ends the application. // ss.addStatement(pf.mkAssumeStatement(new // Attribute[]{pf.mkNoVerifyAttribute()}, // pf.mkBooleanLiteral(false))); ss.addStatement(pf.mkReturnStatement()); return true; } if (ivk.getMethod() .getSignature() .contains( "java.lang.Throwable: void addSuppressed(java.lang.Throwable)")) { ss.addStatement(TranslationHelpers.mkLocationAssertion( ss.getCurrentStatement(), true)); return true; } if (ivk.getMethod().getSignature().contains("addSuppressed")) { System.err.println(ivk.getMethod().getSignature()); } return false; }
private List<Unit> instrumentIntentAddings(BiDiInterproceduralCFG<Unit, SootMethod> cfg, Unit unit, InvokeExpr sinkExpr, Set<ResultSourceInfo> sourceInfo){ if(isMethodInterComponentSink(sinkExpr.getMethod())){ SootMethod method = cfg.getMethodOf(unit); Body body = null; if(method.hasActiveBody()) body = method.retrieveActiveBody(); else throw new RuntimeException("No body found!"); Set<String> sourceCategories = getDataIdList(sourceInfo); final String hashSetType = "java.util.HashSet"; List<Unit> generated = new ArrayList<Unit>(); //HashSet initialization Local hashSetLocal = generateFreshLocal(body, RefType.v(hashSetType)); NewExpr newExpr = Jimple.v().newNewExpr(RefType.v(hashSetType)); AssignStmt assignStmt = Jimple.v().newAssignStmt(hashSetLocal, newExpr); generated.add(assignStmt); //constructor call SpecialInvokeExpr constructorCall = Jimple.v().newSpecialInvokeExpr(hashSetLocal, Scene.v().getMethod("<java.util.HashSet: void <init>()>").makeRef()); InvokeStmt constructorCallStmt = Jimple.v().newInvokeStmt(constructorCall); generated.add(constructorCallStmt); //add categories to HashSet for(String cat : sourceCategories){ InterfaceInvokeExpr addCall = Jimple.v().newInterfaceInvokeExpr(hashSetLocal, Scene.v().getMethod("<java.util.Set: boolean add(java.lang.Object)>").makeRef(), StringConstant.v(cat)); InvokeStmt addCallStmt = Jimple.v().newInvokeStmt(addCall); generated.add(addCallStmt); } //get Intent Value intent = sinkExpr.getArg(0); List<Object> args = new ArrayList<Object>(); args.add(RefType.v("android.content.Intent")); args.add(intent); args.add(RefType.v(hashSetType)); args.add(hashSetLocal); StaticInvokeExpr sie = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "addTaintInformationToIntent", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(sie); generated.add(invStmt); return generated; } return Collections.emptyList(); }
@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { throwInvalidWriteException(v); }
@Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { handleBase(v.getBase()); handleInvoke(v); }
/** * Computes the targets of an invoke expression using a given points-to graph. * * <p>For static invocations, there is only target. For instance method * invocations, the targets depend on the type of receiver objects pointed-to * by the instance variable whose method is being invoked.</p> * * <p>If the instance variable points to a summary node, then the returned * value is <tt>null</tt> signifying a <em>default</em> call-site.</p> */ private Set<SootMethod> getTargets(SootMethod callerMethod, Stmt callStmt, InvokeExpr ie, PointsToGraph ptg) { Set<SootMethod> targets = new HashSet<SootMethod>(); SootMethod invokedMethod = ie.getMethod(); String subsignature = invokedMethod.getSubSignature(); // Static and special invocations refer to the target method directly if (ie instanceof StaticInvokeExpr || ie instanceof SpecialInvokeExpr) { targets.add(invokedMethod); return targets; } else { assert (ie instanceof InterfaceInvokeExpr || ie instanceof VirtualInvokeExpr); // Get the receiver Local receiver = (Local) ((InstanceInvokeExpr) ie).getBase(); // Get what objects the receiver points-to Set<AnyNewExpr> heapNodes = ptg.getTargets(receiver); if (heapNodes != null) { // For each object, find the invoked method for the declared type for (AnyNewExpr heapNode : heapNodes) { if (heapNode == PointsToGraph.SUMMARY_NODE) { // If even one pointee is a summary node, then this is a default site return null; } else if (heapNode instanceof NewArrayExpr) { // Probably getClass() or something like that on an array return null; } // Find the top-most class that declares a method with the given // signature and add it to the resulting targets SootClass sootClass = ((RefType) heapNode.getType()).getSootClass(); do { if (sootClass.declaresMethod(subsignature)) { targets.add(sootClass.getMethod(subsignature)); break; } else if (sootClass.hasSuperclass()) { sootClass = sootClass.getSuperclass(); } else { sootClass = null; } } while (sootClass != null); } } if (targets.isEmpty()) { // System.err.println("Warning! Null call at: " + callStmt+ " in " + callerMethod); } return targets; } }
/** * Looks up the <em>security level</em> of the given invoke expression with * the type {@link SpecialInvokeExpr} and stores the resulting level in * {@link SecurityLevelValueReadSwitch#level}. Also the parameter * <em>security level</em> and the <em>write effects</em> will be handled. * Additionally, the base of the invoke expression will be checked and if * the level of the base if stronger than the resulting * <em>security level</em> of the invoke expression, then this base * <em>security level</em> will be stored in * {@link SecurityLevelValueReadSwitch#level}. * * @param v * The invoke expression, for which the level should be looked * up. * @see soot.jimple.ExprSwitch#caseSpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) * @see SecurityLevelValueReadSwitch#handleInvokeExpr(InvokeExpr) * @see SecurityLevelValueReadSwitch#handleBase(Value, Value) */ @Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { handleInvokeExpr(v); Value base = v.getBase(); handleBase(base, v); }
/** * The method should update the <em>security level</em> of an invoke * expression with type {@link SpecialInvokeExpr}, but it is not possible to * update the level of an invoke expression. * * @param v * The invoke expression for which the <em>security level</em> * should be updated. * @see soot.jimple.ExprSwitch#caseSpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) * @throws InvalidSwitchException * Always, because the update is not possible. */ @Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { throw new SwitchException(getMsg("exception.analysis.switch.update_error", this.getClass().getSimpleName(), v.getClass().getSimpleName(), v.toString(), getSourceLine())); }
/** * Returns true if a method call is fixed, i.e., assuming that all classes in the Scene resemble library code, * then client code cannot possible overwrite the called method. * This is trivially true for InvokeStatic and InvokeSpecial, but can also hold for virtual invokes if * all possible call targets in the library cannot be overwritten. * @see #clientOverwriteableOverwrites(SootMethod) */ public static boolean isFixed(InvokeExpr ie) { return ie instanceof StaticInvokeExpr || ie instanceof SpecialInvokeExpr || !clientOverwriteableOverwrites(ie.getMethod()); }
/** * DOC * * @see soot.jimple.ExprSwitch#caseSpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) */ @Override public void caseSpecialInvokeExpr(SpecialInvokeExpr v) { this.extractor.addMethodEnvironmentForMethod(v.getMethod()); }