/** * Clone given method into this class with given name. Update necessary state of prior analyses. */ private SootMethod cloneMethod(SootMethod ancestorM, String cloneName) { // check if we are cloning a method multiple times if (clonedToOriginal.containsValue(ancestorM)) { logger.error("Cloning method twice: {}", ancestorM); droidsafe.main.Main.exit(1); } SootMethod newMeth = new SootMethod( cloneName, ancestorM.getParameterTypes(), ancestorM.getReturnType(), ancestorM.getModifiers(), ancestorM.getExceptions()); // System.out.printf("\tAdding method %s.\n", ancestorM); // register method methods.addMethod(newMeth); clazz.addMethod(newMeth); clonedToOriginal.put(newMeth, ancestorM); API.v().cloneMethodClassifications(ancestorM, newMeth); // clone body Body newBody = (Body) ancestorM.retrieveActiveBody().clone(); newMeth.setActiveBody(newBody); JSAStrings.v().updateJSAResults(ancestorM.retrieveActiveBody(), newBody); return newMeth; }
/** * Resolve the concrete target of a special invoke using our modified semantics for special invoke * expression. */ private SootMethod resolveSpecialInvokeTarget(SpecialInvokeExpr si) { SootMethod target = null; try { target = SootUtils.resolve(si.getMethodRef()); } catch (CannotFindMethodException e) { logger.error("Cannot find concrete method target for special invoke: {}", si); return null; } String targetSubSig = target.getSubSignature(); SootClass current = target.getDeclaringClass(); while (true) { if (current.declaresMethod(targetSubSig)) { return current.getMethod(targetSubSig); } // not a match in current, try superclass on next loop if (current.hasSuperclass()) current = current.getSuperclass(); else { logger.error("Cannot find concrete method target for special invoke: {}", si); droidsafe.main.Main.exit(1); return null; } } }
/** * Clone non-static ancestor methods that are not hidden by virtual dispatch and that are * reachable based on a pta run. */ private void cloneReachableNonHiddenAncestorMethods(SootClass ancestor) { if (ClassCloner.isClonedClass(ancestor)) { logger.error("Cloning method from clone: {}", ancestor); droidsafe.main.Main.exit(1); } // create all methods, cloning body, replacing instance field refs for (SootMethod ancestorM : ancestor.getMethods()) { if (ancestorM.isAbstract() || ancestorM.isPhantom() || !ancestorM.isConcrete() || SootUtils.isRuntimeStubMethod(ancestorM)) continue; // never clone static methods if (ancestorM.isStatic()) continue; // clone only reachable methods if (!cloneAllMethods && !PTABridge.v().getReachableMethods().contains(ancestorM)) continue; // check if this method already exists if (containsMethod(ancestorM.getSignature())) { // System.out.printf("\tAlready contains method %s.\n", ancestorM); continue; } // turn off final for ancestor methods if (ancestorM.isFinal()) ancestorM.setModifiers(ancestorM.getModifiers() ^ Modifier.FINAL); cloneMethod(ancestorM, ancestorM.getName()); } }
@Override public Set<? extends IAllocNode> getPTSet(Value val, Context context) { // handle case for insensitive run if (k == 0) return getPTSetIns(val); final Set<AllocNode> allocNodes = new LinkedHashSet<AllocNode>(); final Type filteringType = val.getType(); PointsToSetInternal pts = null; try { if (val instanceof InstanceFieldRef) { final InstanceFieldRef ifr = (InstanceFieldRef) val; pts = (PointsToSetInternal) ptsProvider.reachingObjects(context, (Local) ifr.getBase(), ifr.getField()); } else if (val instanceof ArrayRef) { ArrayRef arrayRef = (ArrayRef) val; pts = (PointsToSetInternal) ptsProvider.reachingObjectsOfArrayElement( ptsProvider.reachingObjects(context, (Local) arrayRef.getBase())); } else if (val instanceof Local) { pts = (PointsToSetInternal) ptsProvider.reachingObjects(context, (Local) val); } else if (val instanceof StaticFieldRef) { SootField field = ((StaticFieldRef) val).getField(); pts = (PointsToSetInternal) ptsProvider.reachingObjects(field); } else if (val instanceof NullConstant) { return allocNodes; } else { logger.error("Unknown reference type for insenstive search: {} {}", val, val.getClass()); droidsafe.main.Main.exit(1); } // visit internal points to set and grab all allocnodes pts.forall( new P2SetVisitor() { public void visit(Node n) { if (typeManager.castNeverFails(n.getType(), filteringType)) allocNodes.add((AllocNode) n); } }); } catch (Exception e) { logger.info("Some sort of error getting context insensitive points to set for {}", val, e); // e.printStackTrace(); } return allocNodes; }
@Override public Set<? extends IAllocNode> getPTSet(IAllocNode node, final SootField f) { if (f.isStatic()) { logger.error("Cannot call getPTSet(node, field) with static field: {}", f); droidsafe.main.Main.exit(1); } final Type filteringType = f.getType(); final Set<AllocNode> allocNodes = new LinkedHashSet<AllocNode>(); HashPointsToSet pointsToSet = new HashPointsToSet(node.getType(), ptsProvider); pointsToSet.add((AllocNode) node); ((PointsToSetInternal) ptsProvider.reachingObjects(pointsToSet, f)) .forall( new P2SetVisitor() { @Override public void visit(Node node) { if (typeManager.castNeverFails(node.getType(), filteringType)) allocNodes.add((AllocNode) node); } }); /* PointsToSetInternal bases = (PointsToSetInternal)ptsProvider.getSetFactory().newSet(node.getType(), ptsProvider); bases.add(node); final PointsToSetInternal pts = ptsProvider.getSetFactory().newSet( (f instanceof SootField) ? ((SootField)f).getType() : null, ptsProvider ); bases.forall( new P2SetVisitor() { public final void visit( Node n ) { Node nDotF = ((AllocNode) n).dot( f ); if(nDotF != null) pts.addAll( nDotF.getP2Set(), null ); }} ); //visit internal points to set and grab all allocnodes pts.forall(new P2SetVisitor() { public void visit(Node n) { allocNodes.add((AllocNode)n); } }); */ return (Set<? extends IAllocNode>) allocNodes; }
/** Create the bi map of NewExpr <-> AllocNode */ private void createNewToAllocMap() { newToAllocNodeMap = HashBiMap.create(); allAllocNodes = new LinkedHashSet<AllocNode>(); Map<SootClass, Integer> nodeCount = new LinkedHashMap<SootClass, Integer>(); int realSize = 0; for (AllocNode node : ptsProvider.getAllocNodes()) { if (!(node instanceof InsensitiveAllocNode)) { logger.error("Found non-insensitive node in ptsProvider.getAllocNodes()"); droidsafe.main.Main.exit(1); } InsensitiveAllocNode insNode = (InsensitiveAllocNode) node; newToAllocNodeMap.put(node.getNewExpr(), insNode); realSize++; allAllocNodes.add(node); // countNode(nodeCount, node); for (Map.Entry<Context, ObjectSensitiveAllocNode> entry : insNode.getContextNodeMap().entrySet()) { allAllocNodes.add(entry.getValue()); // countNode(nodeCount, node); } } System.out.println("Alloc node size (insensitive objects): " + realSize); /* used to print a sorted list of alloc nodes created Map<SootClass, Integer> sortedNodeCount = SootUtils.sortByValue(nodeCount); for (Map.Entry<SootClass, Integer> entry : sortedNodeCount.entrySet()) { System.out.println(entry.getValue() + " " + entry.getKey()); } */ }