private Iterator<SootMethod> getPublicNullaryMethodIterator(final SootClass baseClass) { if (baseClass.isPhantom()) { return Collections.emptyIterator(); } return new AbstractMethodIterator(baseClass) { @Override protected boolean acceptMethod(SootMethod n) { int nParams = n.getParameterCount(); return nParams == 0; } }; }
private Iterator<SootMethod> getPublicMethodIterator(final SootClass baseClass, final Set<Type> reachingTypes, final BitSet methodSizes, final boolean mustNotBeNull) { if (baseClass.isPhantom()) { return Collections.emptyIterator(); } return new AbstractMethodIterator(baseClass) { @Override protected boolean acceptMethod(SootMethod n) { int nParams = n.getParameterCount(); if (methodSizes != null) { // if the arg array can be null we have to still allow for // nullary methods boolean compatibleSize = methodSizes.get(nParams) || (!mustNotBeNull && nParams == 0); if (!compatibleSize) { return false; } } List<Type> t = n.getParameterTypes(); for (Type pTy : t) { if (!isReflectionCompatible(pTy, reachingTypes)) { return false; } } return true; } }; }
/** * WARNING: interfaces are subclasses of the java.lang.Object class! Returns the superclass of this class. (see * hasSuperclass()) */ public SootClass getSuperclass() { checkLevel(HIERARCHY); if (superClass == null && !isPhantom()) { throw new RuntimeException("no superclass for " + getName()); } else { return superClass; } }
/** * Loads the given class and all of the required support classes. Returns the first class. */ public SootClass loadClassAndSupport(String className) { SootClass ret = loadClass(className, SootClass.SIGNATURES); if (!ret.isPhantom()) { ret = loadClass(className, SootClass.BODIES); } return ret; }
@Override public void setPhantom(boolean value) { if (value) { if (!Scene.v().allowsPhantomRefs()) { throw new RuntimeException("Phantom refs not allowed"); } if (!Options.v().allow_phantom_elms() && declaringClass != null && !declaringClass.isPhantom()) { throw new RuntimeException("Declaring class would have to be phantom"); } } isPhantom = value; }
/** Sets the phantom flag on this method. */ @Override public void setPhantom(boolean value) { if (value) { if (!Scene.v().allowsPhantomRefs()) { throw new RuntimeException("Phantom refs not allowed"); } if (!Options.v().allow_phantom_elms() && declaringClass != null && !declaringClass.isPhantom()) { throw new RuntimeException("Declaring class would have to be phantom"); } } isPhantom = value; }
/** * 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 true if child 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 isClassSubclassOf(SootClass child, SootClass possibleParent) { child.checkLevel(SootClass.HIERARCHY); possibleParent.checkLevel(SootClass.HIERARCHY); List<SootClass> parentClasses = getSuperclassesOf(child); if (parentClasses.contains(possibleParent)) { return true; } for (SootClass sc : parentClasses) { if (sc.isPhantom()) { return true; } } return false; }
public void add(SootClass c) { if (c.isPhantom()) { return; } addAsClassDefItem(c); // save original APK for this class, needed to copy all the other files // inside Map<String, File> dexClassIndex = SourceLocator.v().dexClassIndex(); if (dexClassIndex == null) { return; // no dex classes were loaded } File sourceForClass = dexClassIndex.get(c.getName()); if (sourceForClass == null || sourceForClass.getName().endsWith(".dex")) { return; // a class was written that was not a dex class or the class // originates from a .dex file, not an APK } if (originalApk != null && !originalApk.equals(sourceForClass)) { throw new CompilationDeathException("multiple APKs as source of an application are not supported"); } originalApk = sourceForClass; }
private static Collection<AncestryTreeNode> buildAncestryTree(RefType root) { if (root.getSootClass().isPhantom()) { return Collections.emptyList(); } LinkedList<AncestryTreeNode> leafs = new LinkedList<AncestryTreeNode>(); leafs.add(new AncestryTreeNode(null, root)); LinkedList<AncestryTreeNode> r = new LinkedList<AncestryTreeNode>(); final RefType objectType = RefType.v("java.lang.Object"); while (!leafs.isEmpty()) { AncestryTreeNode node = leafs.remove(); if (TypeResolver.typesEqual(node.type, objectType)) { r.add(node); } else { SootClass sc = node.type.getSootClass(); for (SootClass i : sc.getInterfaces()) { leafs.add(new AncestryTreeNode(node, (i).getType())); } // The superclass of all interfaces is Object // -- try to discard phantom interfaces. if ((!sc.isInterface() || sc.getInterfaceCount() == 0) && !sc.isPhantom()) { leafs.add(new AncestryTreeNode(node, sc.getSuperclass().getType())); } } } return r; }
public JInterfaceInvokeExpr(Value base, SootMethodRef methodRef, List<? extends Value> args) { super(Jimple.v().newLocalBox(base), methodRef, new ValueBox[args.size()]); // Check that the method's class is resolved enough // CheckLevel returns without doing anything because we can be not 'done' resolving methodRef.declaringClass().checkLevelIgnoreResolving(SootClass.HIERARCHY); // now check if the class is valid if (!methodRef.declaringClass().isInterface() && !methodRef.declaringClass().isPhantom()) { throw new RuntimeException("Trying to create interface invoke expression for non-interface type: " + methodRef.declaringClass() + " Use JVirtualInvokeExpr or JSpecialInvokeExpr instead!"); } for (int i = 0; i < args.size(); i++) { this.argBoxes[i] = Jimple.v().newImmediateBox(args.get(i)); } }
/** Converts a given string class name into a SootClass. * * @param name The dex string representation of the class * @param kind The MethodHandle.Kind of the MethodHandle this class is coming from * @return */ protected SootClass convertClassName(String name, Kind kind) { if (name.startsWith("[")) { name = "java.lang.Object"; } else { name = dottedClassName(name); } SootClass sc = SootResolver.v().makeClassRef(name); if (kind == Kind.REF_INVOKE_INTERFACE && sc.isPhantom()) { sc.setModifiers(sc.getModifiers() | Modifier.INTERFACE); } return sc; }
private boolean isCallToSuper(SpecialInvokeExpr sie) { SootClass classWithInvokation = sie.getMethod().getDeclaringClass(); SootClass currentClass = stmtV.getBelongingClass(); while (currentClass != null) { currentClass = currentClass.getSuperclassUnsafe(); if (currentClass != null) { if (currentClass == 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 }
if (!sootcls.isApplicationClass() && !sootcls.isPhantom()) { sootcls.setLibraryClass();
@Override public void caseInterfaceInvokeInst(InterfaceInvokeInst i) { SootMethodRef m = i.getMethodRef(); SootClass declaration = m.declaringClass(); boolean isInterface = true; if (!declaration.isPhantom() && !declaration.isInterface()) { /* * If the declaring class of a method called via invokeinterface is a phantom class we assume the declaring class * to be an interface. This might not be true in general, but as of today Soot can not evaluate isInterface() for * phantom classes correctly. */ isInterface = false; } mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, slashify(declaration.getName()), m.name(), toTypeDesc(m), isInterface); }
@Override protected String getCommonSuperClass(String type1, String type2) { String typeName1 = type1.replace('/', '.'); String typeName2 = type2.replace('/', '.'); SootClass s1 = Scene.v().getSootClass(typeName1); SootClass s2 = Scene.v().getSootClass(typeName2); // If these two classes haven't been loaded yet or are phantom, we take // java.lang.Object as the common superclass final Type mergedType; if (s1.isPhantom() || s2.isPhantom() || s1.resolvingLevel() == SootClass.DANGLING || s2.resolvingLevel() == SootClass.DANGLING) { mergedType = Scene.v().getObjectType(); } else { Type t1 = s1.getType(); Type t2 = s2.getType(); mergedType = t1.merge(t2, Scene.v()); } if (mergedType instanceof RefType) { return slashify(((RefType) mergedType).getClassName()); } else { throw new RuntimeException("Could not find common super class"); } }
while (classesIt.hasNext()) { SootClass sClass = (SootClass) classesIt.next(); if (sClass.isPhantom()) { continue;
return; if (currClass.hasSuperclass() && !currClass.getSuperclass().isPhantom() && !currClass.getSuperclass().getName().equals("java.lang.Object")) { currClass = currClass.getSuperclass();
SootClass sc = worklist[i].pop(); if (resolveEverything()) { // Whole program mode boolean onlySignatures = sc.isPhantom() || (Options.v().no_bodies_for_excluded() && Scene.v().isExcluded(sc) && !Scene.v().getBasicClasses().contains(sc.getName())); if (onlySignatures) {
if (s.isPhantom()) { continue;