/** * Given an abstract dispatch to an object of type c and a method m, gives a list of possible receiver methods. */ public List<SootMethod> resolveAbstractDispatch(SootClass c, SootMethod m) { c.checkLevel(SootClass.HIERARCHY); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); checkState(); Set<SootMethod> s = new ArraySet<SootMethod>(); Collection<SootClass> classesIt; if (c.isInterface()) { Set<SootClass> classes = new HashSet<SootClass>(); for (SootClass sootClass : getImplementersOf(c)) { classes.addAll(getSubclassesOfIncluding(sootClass)); } classesIt = classes; } else { classesIt = getSubclassesOfIncluding(c); } for (SootClass cl : classesIt) { if (!Modifier.isAbstract(cl.getModifiers())) { s.add(resolveConcreteDispatch(cl, m)); } } return Collections.unmodifiableList(new ArrayList<SootMethod>(s)); }
private Set<SootClass> getChildrenOfIncluding(Collection<SootClass> classes) { return Stream .concat(classes.stream().filter(c -> !c.getName().equals("java.lang.Object")) .map(c -> c.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(c) : Scene.v().getActiveHierarchy().getSubclassesOf(c)) .flatMap(Collection::stream), classes.stream()) .collect(toSet()); }
/** * Returns a list of superclasses of {@code sootClass}, including itself. * * @param sootClass * the <strong>class</strong> of which superclasses will be taken. Must not be {@code null} or interface * @return list of superclasses, including itself * @throws IllegalArgumentException * when passed class is an interface * @throws NullPointerException * when passed argument is {@code null} */ public List<SootClass> getSuperclassesOfIncluding(SootClass sootClass) { final List<SootClass> superclasses = getSuperclassesOf(sootClass); final List<SootClass> result = new ArrayList<>(superclasses.size() + 1); result.add(sootClass); result.addAll(superclasses); return Collections.unmodifiableList(result); }
/** Returns a list of subclasses of c, excluding itself. */ public List<SootClass> getSubclassesOf(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) { throw new RuntimeException("class needed!"); } checkState(); // If already cached, return the value. if (classToSubclasses.get(c) != null) { return classToSubclasses.get(c); } // Otherwise, build up the hashmap. List<SootClass> l = new ArrayList<SootClass>(); for (SootClass cls : classToDirSubclasses.get(c)) { if (cls.resolvingLevel() < SootClass.HIERARCHY) { continue; } l.addAll(getSubclassesOfIncluding(cls)); } l = Collections.unmodifiableList(l); classToSubclasses.put(c, l); return l; }
/** * Gets all child classes of the given class. If the given class is an * interface, all implementors of this interface and its all of child- * interfaces are returned. * * @param sc The class or interface for which to get the children * @return The children of the given class or interface */ private Set<SootClass> getAllChildClasses(SootClass sc) { List<SootClass> workList = new ArrayList<SootClass>(); workList.add(sc); Set<SootClass> doneSet = new HashSet<SootClass>(); Set<SootClass> classes = new HashSet<>(); while (!workList.isEmpty()) { SootClass curClass = workList.remove(0); if (!doneSet.add(curClass)) continue; if (curClass.isInterface()) { workList.addAll(hierarchy.getImplementersOf(curClass)); workList.addAll(hierarchy.getSubinterfacesOf(curClass)); } else { workList.addAll(hierarchy.getSubclassesOf(curClass)); classes.add(curClass); } } return classes; }
/** * 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); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); checkState(); if (concreteType.isInterface()) { throw new RuntimeException("class needed!"); } String methodSig = m.getSubSignature(); for (SootClass c : getSuperclassesOfIncluding(concreteType)) { SootMethod sm = c.getMethodUnsafe(methodSig); if (sm != null && isVisible(c, m)) { return sm; } } throw new RuntimeException("could not resolve concrete dispatch!\nType: " + concreteType + "\nMethod: " + m); }
/** * If exception e is caught at unit u in body b, return true; otherwise, return false. */ public static boolean isExceptionCaughtAt(SootClass e, Unit u, Body b) { /* * Look through the traps t of b, checking to see if: - caught exception is e; - and, unit lies between t.beginUnit and * t.endUnit */ Hierarchy h = Scene.v().getActiveHierarchy(); Chain<Unit> units = b.getUnits(); for (Trap t : b.getTraps()) { /* Ah ha, we might win. */ if (h.isClassSubclassOfIncluding(e, t.getException())) { Iterator<Unit> it = units.iterator(t.getBeginUnit(), units.getPredOf(t.getEndUnit())); while (it.hasNext()) { if (u.equals(it.next())) { return true; } } } } return false; }
if (classOne.isInterface()) { if (classTwo.isInterface()) { typeCompatible = h.getSubinterfacesOfIncluding(classOne).contains(classTwo) || h.getSubinterfacesOfIncluding(classTwo).contains(classOne); } else { typeCompatible = h.getImplementersOf(classOne).contains(classTwo); typeCompatible = h.getImplementersOf(classTwo).contains(classOne); } else { typeCompatible = (classOne != null && Scene.v().getActiveHierarchy().getSubclassesOfIncluding(classOne).contains(classTwo) || classTwo != null && Scene.v().getActiveHierarchy().getSubclassesOfIncluding(classTwo).contains(classOne));
if (rightClass.isInterface()) { if (!(leftClass.getName().equals(rightClass.getName()) || Scene.v().getActiveHierarchy().isInterfaceSubinterfaceOf(rightClass, leftClass))) { exception.add(new ValidationException(stmt, "Warning: Bad use of interface type" + errorSuffix + " in " + body.getMethod())); + errorSuffix + " in " + body.getMethod())); } else { if (!Scene.v().getActiveHierarchy().isClassSubclassOfIncluding(rightClass, leftClass)) { exception.add( new ValidationException(stmt, "Warning: Bad use of class type" + errorSuffix + " in " + body.getMethod()));
/** * Returns true if child is, or is a subclass of, possibleParent. If one of the known parent classes is phantom, we * conservatively assume that the current class might be a child. */ public boolean isClassSubclassOfIncluding(SootClass child, SootClass possibleParent) { child.checkLevel(SootClass.HIERARCHY); possibleParent.checkLevel(SootClass.HIERARCHY); List<SootClass> parentClasses = getSuperclassesOfIncluding(child); if (parentClasses.contains(possibleParent)) { return true; } for (SootClass sc : parentClasses) { if (sc.isPhantom()) { return true; } } return false; }
/** 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; } } }
/** Returns true if parent is, or is a superclass of, possibleChild. */ public boolean isClassSuperclassOfIncluding(SootClass parent, SootClass possibleChild) { parent.checkLevel(SootClass.HIERARCHY); possibleChild.checkLevel(SootClass.HIERARCHY); return getSubclassesOfIncluding(parent).contains(possibleChild); }
if (sootClass2.isInterface()) { haveCommonFields = hierarchy.isInterfaceSubinterfaceOf(sootClass1, sootClass2) || hierarchy.isInterfaceSuperinterfaceOf(sootClass1, sootClass2); if (logger.isDebugEnabled()) { logger.debug("1: " + haveCommonFields); hierarchy.isClassSubclassOf(sootClass1, sootClass2) || hierarchy.isClassSuperclassOf(sootClass1, sootClass2); if (logger.isDebugEnabled()) { logger.debug("4: " + haveCommonFields);
/** Returns a list of subclasses of c, including itself. */ public List<SootClass> getSubclassesOfIncluding(SootClass c) { c.checkLevel(SootClass.HIERARCHY); if (c.isInterface()) { throw new RuntimeException("class needed!"); } List<SootClass> l = new ArrayList<SootClass>(); l.addAll(getSubclassesOf(c)); l.add(c); return Collections.unmodifiableList(l); }
@Override public int compare(final SootClass a, final SootClass b) { if (a == b) return 0; if (hierarchy.isClassSubclassOf(a, b)) return 1; if (hierarchy.isClassSuperclassOf(a, b)) return -1; return 0; } });
private Optional<SootMethod> findAccessibleInSuperClassesBySubSig(SootClass base, String subSig) { Hierarchy hierarchy = Scene.v().getActiveHierarchy(); for (SootClass superClass : hierarchy.getSuperclassesOfIncluding(base.getSuperclass())) { if (superClass.isLibraryClass() && superClass.declaresMethod(subSig)) { SootMethod method = superClass.getMethod(subSig); if (hierarchy.isVisible(base, method)) { return Optional.of(method); } } } return Optional.empty(); } }
List<SootClass> classes = null; if (sc.isInterface()) { classes = hierarchy.getImplementersOf(sc); } else { try { classes = hierarchy.getSubclassesOfIncluding(sc); } catch (Throwable e) { SootClass exceptionClass = Scene.v().getSootClass("java.lang.Exception"); System.err.print("There is a bug ..."); classes = hierarchy.getSubclassesOfIncluding(exceptionClass);
/** * If exception e is caught at stmt s in body b, return the handler; otherwise, return null. */ static boolean isExceptionCaughtAt(SootClass e, Stmt stmt, Body b) { /* * Look through the traps t of b, checking to see if: - caught exception is e; - and, stmt lies between t.beginUnit and * t.endUnit */ Hierarchy h = new Hierarchy(); Iterator<Trap> trapsIt = b.getTraps().iterator(); while (trapsIt.hasNext()) { Trap t = trapsIt.next(); /* Ah ha, we might win. */ if (h.isClassSubclassOfIncluding(e, t.getException())) { Iterator<Unit> it = b.getUnits().iterator(t.getBeginUnit(), t.getEndUnit()); while (it.hasNext()) { if (stmt.equals(it.next())) { return true; } } } } return false; } }
for (Trap t : surroundingTraps) { if (hierarchy.isClassSubclassOfIncluding(t.getException(), thrownException) || hierarchy.isClassSubclassOfIncluding(thrownException, t.getException())) { if (!possibleExceptions.contains(t.getException())) { possibleExceptions.add(t.getException()); if (hierarchy.isClassSubclassOf(thrownException, t.getException())) { catchesThrownException = true; if (hierarchy.isClassSubclassOfIncluding(exception, t.getException())) { trap = t; break;
for (SootClass parentClass : Scene.v().getActiveHierarchy().getSuperclassesOf(sootClass)) { if (SystemClassHandler.isClassInSystemPackage(parentClass.getName())) for (SootMethod sm : parentClass.getMethods()) for (SootClass parentClass : Scene.v().getActiveHierarchy().getSubclassesOfIncluding(sootClass)) { if (SystemClassHandler.isClassInSystemPackage(parentClass.getName())) continue;