protected ReferenceVariable arrayElementOfImpl(ReferenceVariable base) { VarNode l; if (base instanceof VarNode) { l = (VarNode) base; } else { FieldRefNode b = (FieldRefNode) base; l = pag.makeGlobalVarNode(b, b.getType()); pag.addEdge(b, l); } return pag.makeFieldRefNode(l, ArrayElement.v()); }
protected void assignObjectToImpl(ReferenceVariable lhs, AbstractObject obj) { AllocNode objNode = pag.makeAllocNode(new Pair("AbstractObject", obj.getType()), obj.getType(), null); VarNode var; if (lhs instanceof FieldRefNode) { var = pag.makeGlobalVarNode(objNode, objNode.getType()); pag.addEdge((Node) lhs, var); } else { var = (VarNode) lhs; } pag.addEdge(objNode, var); }
@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; }
public Set<? extends IAllocNode> getPTSetOfArrayElement(IAllocNode allocNode) { final Set<AllocNode> ptSet = new LinkedHashSet<AllocNode>(); if (!(allocNode.getType() instanceof ArrayType)) { logger.error( "Calling getPTSetOfArrayElement on non array type: {} with {}", allocNode, allocNode.getType()); } final Type filteringType = ((ArrayType) allocNode.getType()).getElementType(); HashPointsToSet pointsToSet = new HashPointsToSet(allocNode.getType(), ptsProvider); pointsToSet.add((AllocNode) allocNode); ((PointsToSetInternal) ptsProvider.reachingObjectsOfArrayElement(pointsToSet)) .forall( new P2SetVisitor() { @Override public void visit(Node node) { if (typeManager.castNeverFails(node.getType(), filteringType)) ptSet.add((AllocNode) node); } }); return (Set<? extends IAllocNode>) ptSet; }
/** constructor, add edges to maps */ public MatchEdges(PAG pag) { Iterator<VarNode> store_it = pag.storeSourcesIterator(); // storeMap: store_src(VarNode) ----> store_targets(FieldRefNode) while (store_it.hasNext()) { // get the representative of the union VarNode from = ((VarNode) store_it.next()); // storeSrc, a Node[] storeTargets = pag.storeLookup(from); for (int i = 0; i < storeTargets.length; i++) { FieldRefNode storeTarget = (FieldRefNode) storeTargets[i]; // x.f VarNode storeTargetBase = storeTarget.getBase(); // x SparkField storeTargetField = storeTarget.getField(); // f String storeTargetFieldSig = ((SootField) storeTargetField).getSignature(); // f's signature // three inheritances of SparkField: // ArrayElement, Parm, and SootField if (storeTargetField instanceof SootField) { Iterator<FieldRefNode> load_it = pag.loadSourcesIterator(); while (load_it.hasNext()) { FieldRefNode loadSrc = (FieldRefNode) load_it.next(); // y.f VarNode loadSrcBase = loadSrc.getBase(); // y SparkField loadSrcField = loadSrc.getField(); // f if (loadSrcField instanceof SootField) { // see whether x.f and y.f has the same offset of // the field String loadSrcFieldSig = ((SootField) loadSrcField).getSignature(); // f's signature if (loadSrcFieldSig.equals(storeTargetFieldSig)) { Node[] to = pag.loadLookup(loadSrc); // loadTargets for (int j = 0; j < to.length; j++) { addMatchEdge(from, (VarNode) to[j]); } } } } } } } }
@SuppressWarnings("unused") private String assignEdgesWellFormed(PAG pag) { for (Iterator iter = pag.getVarNodeNumberer().iterator(); iter.hasNext(); ) { VarNode v = (VarNode) iter.next(); Set<AssignEdge> outgoingAssigns = getAssignBarEdges(v); for (AssignEdge edge : outgoingAssigns) { if (edge.getSrc() != v) return edge + " src should be " + v; } Set<AssignEdge> incomingAssigns = getAssignEdges(v); for (AssignEdge edge : incomingAssigns) { if (edge.getDst() != v) return edge + " dst should be " + v; } } return null; }
@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; }
@Override protected void runInternal() { // don't print crap to screen! G.v().out = new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM); Scene.v().loadDynamicClasses(); setSparkPointsToAnalysis(); // other passes can print crap now G.v().out = System.out; ptsProvider = (PAG) Scene.v().getPointsToAnalysis(); typeManager = ptsProvider.getTypeManager(); // cache the call graph callGraph = Scene.v().getCallGraph(); createNewToAllocMap(); /* for (SootMethod method : getReachableMethods()) { Set<MethodOrMethodContext> mcs = getMethodContexts(method); if (mcs.size() > 30) System.out.println(method + " " + mcs.size()); } */ // dumpReachablesAndAllocNodes(); // dumpCallGraphReachablesCSV(); // dumpOutdegreesCSV(); if (Config.v().dumpPta) { dumpPTA(Project.v().getOutputDir() + File.separator + "pta.txt"); } if (Config.v().dumpCallGraph) { // dumpCallGraph(Project.v().getOutputDir() + File.separator + "callgraph.dot"); String fileName = String.format("callgraph%d.txt", runCount++); dumpTextGraph(Project.v().getOutputDir() + File.separator + fileName); } // System.out.println(SparkEvaluator.v().toString()); }
/** 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()); } */ }
private void dumpReachablesAndAllocNodes() { try { FileWriter fw = new FileWriter(Project.v().getOutputDir() + File.separator + "spark-dump.log"); fw.write("# Reachable Method Contexts:\n\n"); for (MethodOrMethodContext momc : getReachableMethodContexts()) { fw.write(momc + "\n\n"); } fw.write("\n\n# AllocNodes: \n\n"); Iterator<AllocNode> nodes = ptsProvider.getAllocNodeNumberer().iterator(); while (nodes.hasNext()) { AllocNode node = nodes.next(); fw.write(node + "\n\n"); } fw.close(); } catch (IOException e) { } }
protected void assignImpl(ReferenceVariable lhs, ReferenceVariable rhs) { pag.addEdge((Node) rhs, (Node) lhs); }
protected void throwExceptionImpl(AbstractObject obj) { AllocNode objNode = pag.makeAllocNode(new Pair("AbstractObject", obj.getType()), obj.getType(), null); pag.addEdge(objNode, pag.nodeFactory().caseThrow()); }
public ContextSensitiveInfo(PAG pag) { // set up method to node map for (Iterator iter = pag.getVarNodeNumberer().iterator(); iter.hasNext(); ) { VarNode varNode = (VarNode) iter.next(); if (varNode instanceof LocalVarNode) { LocalVarNode local = (LocalVarNode) varNode; SootMethod method = local.getMethod(); assert method != null : local; methodToNodes.put(method, local); if (SootUtil.isRetNode(local)) { methodToOutPorts.put(method, local); } if (SootUtil.isParamNode(local)) { methodToInPorts.put(method, local); } } } int callSiteNum = 0; // first, add regular assigns Set assignSources = pag.simpleSources(); for (Iterator iter = assignSources.iterator(); iter.hasNext(); ) { VarNode assignSource = (VarNode) iter.next(); if (skipNode(assignSource)) { continue; } boolean sourceGlobal = assignSource instanceof GlobalVarNode; Node[] assignTargets = pag.simpleLookup(assignSource); for (int i = 0; i < assignTargets.length; i++) { VarNode assignTarget = (VarNode) assignTargets[i]; if (skipNode(assignTarget)) continue; boolean isFinalizerNode = false; if (assignTarget instanceof LocalVarNode) { LocalVarNode local = (LocalVarNode) assignTarget; SootMethod method = local.getMethod(); if (method.toString().indexOf("finalize()") != -1 && SootUtil.isThisNode(local)) { isFinalizerNode = true; } } boolean targetGlobal = assignTarget instanceof GlobalVarNode; AssignEdge assignEdge = new AssignEdge(assignSource, assignTarget); // handle weird finalizers if (isFinalizerNode) { assignEdge.setParamEdge(); Integer callSite = new Integer(callSiteNum++); assignEdge.setCallSite(callSite); } addAssignEdge(assignEdge); if (sourceGlobal) { if (targetGlobal) { // System.err.println("G2G " + assignSource + " --> " // + assignTarget); } else { SootMethod method = ((LocalVarNode) assignTarget).getMethod(); // don't want to include things assigned something that // is already an in port if (!methodToInPorts.get(method).contains(assignTarget)) { methodToInPorts.put(method, assignSource); } } } else { if (targetGlobal) { SootMethod method = ((LocalVarNode) assignSource).getMethod(); // don't want to include things assigned from something // that // is already an out port if (!methodToOutPorts.get(method).contains(assignSource)) { methodToOutPorts.put(method, assignTarget); } } } } } // now handle calls HashMultiMap callAssigns = pag.callAssigns; PrintWriter callSiteWriter = null; if (PRINT_CALL_SITE_INFO) { try { callSiteWriter = new PrintWriter(new FileWriter("callSiteInfo"), true); } catch (IOException e) { e.printStackTrace(); } } for (Iterator iter = callAssigns.keySet().iterator(); iter.hasNext(); ) { InvokeExpr ie = (InvokeExpr) iter.next(); Integer callSite = new Integer(callSiteNum++); callSiteToInvokedMethod.put(callSite, ie.getMethod()); SootMethod invokingMethod = pag.callToMethod.get(ie); callSiteToInvokingMethod.put(callSite, invokingMethod); if (PRINT_CALL_SITE_INFO) { callSiteWriter.println(callSite + " " + callSiteToInvokingMethod.get(callSite) + " " + ie); } if (pag.virtualCallsToReceivers.containsKey(ie)) { LocalVarNode receiver = (LocalVarNode) pag.virtualCallsToReceivers.get(ie); assert receiver != null; virtCallSiteToReceiver.put(callSite, receiver); receiverToVirtCallSites.put(receiver, callSite); } Set curEdges = callAssigns.get(ie); for (Iterator iterator = curEdges.iterator(); iterator.hasNext(); ) { Pair callAssign = (Pair) iterator.next(); VarNode src = (VarNode) callAssign.getO1(); VarNode dst = (VarNode) callAssign.getO2(); if (skipNode(src)) { continue; } ArraySet edges = getAssignBarEdges(src); AssignEdge edge = null; for (int i = 0; i < edges.size() && edge == null; i++) { AssignEdge curEdge = (AssignEdge) edges.get(i); if (curEdge.getDst() == dst) { edge = curEdge; } } assert edge != null : "no edge from " + src + " to " + dst; boolean edgeFromOtherCallSite = edge.isCallEdge(); if (edgeFromOtherCallSite) { edge = new AssignEdge(src, dst); } edge.setCallSite(callSite); callSiteToEdges.put(callSite, edge); if (SootUtil.isParamNode(dst)) { // assert src instanceof LocalVarNode : src + " " + dst; edge.setParamEdge(); SootMethod invokedMethod = ((LocalVarNode) dst).getMethod(); callSiteToTargets.put(callSite, invokedMethod); callSitesInvokingMethod.put(invokedMethod, callSite); // assert src instanceof LocalVarNode : src + " NOT LOCAL"; if (src instanceof LocalVarNode) { callSitesInMethod.put(((LocalVarNode) src).getMethod(), callSite); } } else if (SootUtil.isRetNode(src)) { edge.setReturnEdge(); SootMethod invokedMethod = ((LocalVarNode) src).getMethod(); callSiteToTargets.put(callSite, invokedMethod); callSitesInvokingMethod.put(invokedMethod, callSite); if (dst instanceof LocalVarNode) { callSitesInMethod.put(((LocalVarNode) dst).getMethod(), callSite); } } else { assert false : "weird call edge " + callAssign; } if (edgeFromOtherCallSite) { addAssignEdge(edge); } } } // System.err.println(callSiteNum + " call sites"); assert callEdgesReasonable(); if (PRINT_CALL_SITE_INFO) { callSiteWriter.close(); } // assert assignEdgesWellFormed(pag) == null : // assignEdgesWellFormed(pag); }
protected ReferenceVariable staticFieldImpl(String className, String fieldName) { SootClass c = RefType.v(className).getSootClass(); SootField f = c.getFieldByName(fieldName); return pag.makeGlobalVarNode(f, f.getType()); }
protected ReferenceVariable newInstanceOfImpl(ReferenceVariable cls) { return pag.nodeFactory().caseNewInstance((VarNode) cls); }
protected ReferenceVariable tempFieldImpl(String fieldsig) { return pag.makeGlobalVarNode(new Pair("tempField", fieldsig), RefType.v("java.lang.Object")); }
protected ReferenceVariable tempVariableImpl() { return pag.makeGlobalVarNode( new Pair("TempVar", new Integer(++G.v().SparkNativeHelper_tempVar)), RefType.v("java.lang.Object")); }
@Override public boolean isPointer(Value val) { return (ptsProvider.findGlobalVarNode(val) != null || ptsProvider.findLocalVarNode(val) != null); }
@Override public boolean isLegalCast(Type objType, Type refType) { return ptsProvider.getTypeManager().castNeverFails(objType, refType); }
protected ReferenceVariable tempLocalVariableImpl(SootMethod method) { return pag.makeLocalVarNode( new Pair("TempVar", new Integer(++G.v().SparkNativeHelper_tempVar)), RefType.v("java.lang.Object"), method); }