final public boolean castNeverFails(Type src, Type dst) { if (fh == null) { return true; } else if (dst == null) { return true; } else if (dst == src) { return true; } else if (src == null) { return false; } else if (src instanceof NullType) { return true; } else if (src instanceof AnySubType) { return true; } else if (dst instanceof NullType) { return false; } else if (dst instanceof AnySubType) { throw new RuntimeException("oops src=" + src + " dst=" + dst); } else { return getFastHierarchy().canStoreType(src, dst); } }
protected boolean isThrowDeclared(Body b, SootClass throwClass) { if (hierarchy == null) { hierarchy = new FastHierarchy(); if (hierarchy.isSubclass(throwClass, Scene.v().getSootClass("java.lang.RuntimeException")) || hierarchy.isSubclass(throwClass, Scene.v().getSootClass("java.lang.Error"))) { return true; while (it.hasNext()) { SootClass nextEx = it.next(); if (hierarchy.isSubclass(throwClass, nextEx)) { return true;
return true; } else if (parent instanceof RefType) { return canStoreClass(((RefType) child).getSootClass(), ((RefType) parent).getSootClass()); } else { return false; Deque<SootClass> worklist = new ArrayDeque<SootClass>(); if (base.isInterface()) { worklist.addAll(getAllImplementersOfInterface(base)); } else { worklist.add(base); } else if (!workset.add(cl)) { continue; } else if (cl.isConcrete() && canStoreClass(cl, parentClass)) { return true; worklist.addAll(getSubclassesOf(cl)); return false; } else { return canStoreType(achild.baseType, aparent.baseType);
/** * For an interface parent (MUST be an interface), returns set of all implementers of it but NOT their subclasses. * * This method can be used concurrently (is thread safe). * * @param parent * the parent interface. * @return an set, possibly empty */ public Set<SootClass> getAllImplementersOfInterface(SootClass parent) { parent.checkLevel(SootClass.HIERARCHY); Set<SootClass> result = interfaceToAllImplementers.get(parent); if (result.size() > 0) { return result; } result = new HashSet<>(); for (SootClass subinterface : getAllSubinterfaces(parent)) { if (subinterface == parent) { continue; } result.addAll(getAllImplementersOfInterface(subinterface)); } result.addAll(interfaceToImplementers.get(parent)); interfaceToAllImplementers.putAll(parent, result); return result; }
return parent == rtObject.getSootClass(); } else { return getAllSubinterfaces(parent).contains(child); final Set<SootClass> impl = getAllImplementersOfInterface(parent); if (impl.size() > 1000) { return canStoreClassClassic(child, parent); } else {
/** 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; } }
public static soot.Local getThisGivenOuter(soot.Type sootType, HashMap getThisMap, soot.Body body, LocalGenerator lg, soot.Local t2) { if (InitialResolver.v().hierarchy() == null) { InitialResolver.v().hierarchy(new soot.FastHierarchy()); } soot.FastHierarchy fh = InitialResolver.v().hierarchy(); while (!fh.canStoreType(t2.getType(), sootType)) { soot.SootClass classToInvoke = ((soot.RefType) t2.getType()).getSootClass(); // make an access method and add it to that class for accessing // its private this$0 field soot.SootMethod methToInvoke = makeOuterThisAccessMethod(classToInvoke); // generate a local that corresponds to the invoke of that meth soot.Local t3 = lg.generateLocal(methToInvoke.getReturnType()); ArrayList methParams = new ArrayList(); methParams.add(t2); soot.Local res = getPrivateAccessFieldInvoke(methToInvoke.makeRef(), methParams, body, lg); soot.jimple.AssignStmt assign = soot.jimple.Jimple.v().newAssignStmt(t3, res); body.getUnits().add(assign); t2 = t3; } getThisMap.put(sootType, t2); return t2; }
if( t instanceof ArrayType ) t = RefType.v( "java.lang.Object" ); if( declaredType != null && !Scene.v().getOrMakeFastHierarchy() .canStoreType( t, declaredType ) ) { return; .canStoreType( t, sigType ) ) { return; cl = worklist.removeFirst(); if( cl.isInterface() ) { for( Iterator cIt = fh.getAllImplementersOfInterface(cl).iterator(); cIt.hasNext(); ) { final SootClass c = (SootClass) cIt.next(); if( workset.add( c ) ) worklist.add( c ); subTypes.add(cl.getType()); for( Iterator cIt = fh.getSubclassesOf( cl ).iterator(); cIt.hasNext(); ) { final SootClass c = (SootClass) cIt.next(); if( workset.add( c ) ) worklist.add( c );
SootClass c = s.iterator().next(); s.remove(c); if (!c.isInterface() && !c.isAbstract() && canStoreClass(c, declaringClass)) { SootMethod concreteM = resolveConcreteDispatch(c, m); if (concreteM != null) { ret.add(concreteM); RefType concreteType = (RefType) t; SootClass concreteClass = concreteType.getSootClass(); if (!canStoreClass(concreteClass, declaringClass)) { continue; SootMethod concreteM = resolveConcreteDispatch(concreteClass, m); if (concreteM != null) { ret.add(concreteM); SootMethod concreteM = resolveConcreteDispatch(rtObject.getSootClass(), m); if (concreteM != null) { ret.add(concreteM);
worklist.addAll(getAllImplementersOfInterface(concreteType)); continue; SootMethod method = concreteType.getMethodUnsafe(methodSig); if (method != null) { if (isVisible(concreteType, m)) { if (method.isAbstract()) { throw new RuntimeException("abstract dispatch resolved to abstract method!\nAbstract Type: " + abstractType
if (Scene.v().getFastHierarchy().isSubclass(originalComponent, calleeClass)) { SootClass targetClass = e.getTgt().method().getDeclaringClass(); return targetClass == originalComponent || Scene.v().getFastHierarchy().isSubclass(targetClass, originalComponent); if (Scene.v().getFastHierarchy().canStoreType(e.tgt().getDeclaringClass().getType(), RefType.v("java.lang.Runnable"))) return false;
/** * Makes a new fast hierarchy is none is active, and returns the active fast hierarchy. */ public FastHierarchy getOrMakeFastHierarchy() { if (!hasFastHierarchy()) { setFastHierarchy(new FastHierarchy()); } return getFastHierarchy(); }
cl = worklist.removeFirst(); if (cl.isInterface()) { for (Iterator<SootClass> cIt = fh.getAllImplementersOfInterface(cl).iterator(); cIt.hasNext();) { final SootClass c = cIt.next(); if (workset.add(c)) { newSubTypes.add(cl.getType()); for (Iterator<SootClass> cIt = fh.getSubclassesOf(cl).iterator(); cIt.hasNext();) { final SootClass c = cIt.next(); if (workset.add(c)) {
/** Constructs a hierarchy from the current scene. */ public FastHierarchy() { this.sc = Scene.v(); /* First build the inverse maps. */ for( Iterator clIt = sc.getClasses().iterator(); clIt.hasNext(); ) { final SootClass cl = (SootClass) clIt.next(); if( cl.resolvingLevel() < SootClass.HIERARCHY ) continue; if( !cl.isInterface() && cl.hasSuperclass() ) { put( classToSubclasses, cl.getSuperclass(), cl ); } for( Iterator superclIt = cl.getInterfaces().iterator(); superclIt.hasNext(); ) { final SootClass supercl = (SootClass) superclIt.next(); if( cl.isInterface() ) { interfaceToSubinterfaces.put( supercl, cl ); } else { interfaceToImplementers.put( supercl, cl ); } } } /* Now do a dfs traversal to get the Interval numbers. */ dfsVisit( 0, Scene.v().getSootClass( "java.lang.Object" ) ); /* also have to traverse for all phantom classes because they also * can be roots of the type hierarchy */ for(SootClass phantomClass: Scene.v().getPhantomClasses()) { if(!phantomClass.isInterface()) dfsVisit( 0, phantomClass ); } }
/** Returns true if the method m is visible from code in the class from. */ private boolean isVisible(SootClass from, SootMethod m) { from.checkLevel(SootClass.HIERARCHY); if (m.isPublic()) { return true; } if (m.isPrivate()) { return from.equals(m.getDeclaringClass()); } if (m.isProtected()) { return canStoreClass(from, m.getDeclaringClass()); } // m is package return from.getJavaPackageName().equals(m.getDeclaringClass().getJavaPackageName()); // || canStoreClass( from, m.getDeclaringClass() ); }
protected int dfsVisit(int start, SootClass c) { Interval r = new Interval(); r.lower = start++; Collection<SootClass> col = classToSubclasses.get(c); if (col != null) { for (SootClass sc : col) { // For some awful reason, Soot thinks interface are subclasses // of java.lang.Object if (sc.isInterface()) { continue; } start = dfsVisit(start, sc); } } r.upper = start++; if (c.isInterface()) { throw new RuntimeException("Attempt to dfs visit interface " + c); } if (!classToInterval.containsKey(c)) { classToInterval.put(c, r); } return start; }
private Collection<Type> getTransitiveSubClasses(Set<SootClass> classRoots) { LinkedList<SootClass> worklist = new LinkedList<>(classRoots); Set<Type> resolved = new HashSet<>(); while (!worklist.isEmpty()) { SootClass cls = worklist.removeFirst(); if (!resolved.add(cls.getType())) { continue; } worklist.addAll(fh.getSubclassesOf(cls)); } return resolved; }
/** * For an interface parent (MUST be an interface), returns set of all subinterfaces including <code>parent</code>. * * This method can be used concurrently (is thread safe). * * @param parent * the parent interface. * @return an set, possibly empty */ public Set<SootClass> getAllSubinterfaces(SootClass parent) { parent.checkLevel(SootClass.HIERARCHY); if (!parent.isInterface()) { return Collections.emptySet(); } Set<SootClass> result = interfaceToAllSubinterfaces.get(parent); if (result.size() > 0) { return result; } result = new HashSet<>(); result.add(parent); for (SootClass si : interfaceToSubinterfaces.get(parent)) { result.addAll(getAllSubinterfaces(si)); } interfaceToAllSubinterfaces.putAll(parent, result); return result; }
/** * Given an object of actual type C (o = new C()), returns the method which will be called on an o.f() invocation. */ public SootMethod resolveConcreteDispatch(SootClass concreteType, SootMethod m) { concreteType.checkLevel(SootClass.HIERARCHY); if (concreteType.isInterface()) { throw new RuntimeException("A concrete type cannot be an interface: " + concreteType); } String methodSig = m.getSubSignature(); while (true) { SootMethod method = concreteType.getMethodUnsafe(methodSig); if (method != null) { if (isVisible(concreteType, m)) { if (method.isAbstract()) { throw new RuntimeException("Error: Method call resolves to abstract method!"); } return method; } } concreteType = concreteType.getSuperclassUnsafe(); if (concreteType == null) { break; } } // When there is no proper dispatch found, we simply return null to let // the caller decide what to do return null; // throw new RuntimeException("could not resolve concrete // dispatch!\nType: "+concreteType+"\nMethod: "+m); }
= fastHierarchy.resolveConcreteDispatch(concreteType.getSootClass(), iie.getMethod()); return Collections.singleton(singleTargetMethod); } else { throw new InternalError("Unexpected base type:" + base.getType()); return fastHierarchy.resolveAbstractDispatch(baseTypeClass, iie.getMethod());