private static PDGNode[] getAllNodesSorted(SDGBuilder builder, IProgressMonitor progress) throws CancelException { ArrayList<PDGNode> nodes = new ArrayList<PDGNode>(); for (PDG pdg : builder.getAllPDGs()) { for (PDGNode node : pdg.vertexSet()) { if (node.getPdgId() == pdg.getId()) { nodes.add(node); } } } PDGNode[] copy = new PDGNode[nodes.size()]; copy = nodes.toArray(copy); progress.worked(1); MonitorUtil.throwExceptionIfCanceled(progress); Arrays.sort( copy, new Comparator<PDGNode>() { public int compare(PDGNode o1, PDGNode o2) { return o1.getId() - o2.getId(); } }); progress.worked(1); MonitorUtil.throwExceptionIfCanceled(progress); return copy; }
private static void addEdgesForNode( SDG sdg, PDGNode node, Map<PDGNode, SDGNode> pdg2sdg, SDGBuilder b) { PDG pdg = b.getPDGforId(node.getPdgId()); SDGNode from = pdg2sdg.get(node); if (!pdg.containsVertex(node)) { throw new IllegalStateException(); } for (PDGEdge edge : pdg.outgoingEdgesOf(node)) { SDGNode to = pdg2sdg.get(edge.to); SDGEdge sdgEdge = createEdge(from, to, edge.kind, edge.getLabel()); sdg.addEdge(from, to, sdgEdge); } }
private void createActualInAndOut( final Map<PDGNode, Node> pdg2cfg, final ModRefCandidates modref, final PDG pdg, final CallGraph cg) { for (final PDGNode call : pdg.getCalls()) { final Node cn = pdg2cfg.get(call); final SSAInvokeInstruction invk = (SSAInvokeInstruction) pdg.getInstruction(call); final CallSiteReference site = invk.getCallSite(); final Set<ModRefFieldCandidate> modRefCands = new HashSet<ModRefFieldCandidate>(); for (final CGNode tgt : cg.getPossibleTargets(pdg.cgNode, site)) { final InterProcCandidateModel tgtModRef = modref.getCandidates(tgt); if (tgtModRef == null) { continue; } for (final ModRefFieldCandidate c : tgtModRef) { modRefCands.add(c); } } final List<ModRefFieldCandidate> refs = new LinkedList<ModRefFieldCandidate>(); final List<ModRefFieldCandidate> mods = new LinkedList<ModRefFieldCandidate>(); for (final ModRefFieldCandidate c : modRefCands) { if (c.isMod()) { mods.add(c); } if (c.isRef()) { refs.add(c); } } addNodesBefore(cn, refs, Node.Kind.ACTUAL_IN); addNodesAfter(cn, mods, Node.Kind.ACTUAL_OUT); } }
private void createInitalNodesAndFlow( final Map<PDGNode, Node> pdg2cfg, final ModRefCandidates modref, final PDG pdg) { final Node nEntry = createNOPNode(pdg.entry); this.entry = nEntry; pdg2cfg.put(pdg.entry, nEntry); final Node nExit = createNOPNode(pdg.exit); this.exit = nExit; pdg2cfg.put(pdg.exit, nExit); for (final PDGField fref : pdg.getFieldReads()) { if (!fref.field.isStatic()) { final SSAInstruction instr = pdg.getInstruction(fref.node); final ModRefFieldCandidate refCand = modref.createRefCandidate(pdg.cgNode, instr); final Node n = createNode(refCand, fref.accfield, Node.Kind.READ); pdg2cfg.put(fref.accfield, n); } } for (final PDGField fmod : pdg.getFieldWrites()) { if (!fmod.field.isStatic()) { final SSAInstruction instr = pdg.getInstruction(fmod.node); final ModRefFieldCandidate refCand = modref.createModCandidate(pdg.cgNode, instr); final Node n = createNode(refCand, fmod.accfield, Node.Kind.WRITE); pdg2cfg.put(fmod.accfield, n); } } for (final PDGNode pn : pdg.vertexSet()) { if (pn.getPdgId() == pdg.getId() && !pdg2cfg.containsKey(pn)) { final Node n = createNOPNode(pn); pdg2cfg.put(pn, n); } } for (final PDGEdge e : pdg.edgeSet()) { if (e.kind == PDGEdge.Kind.CONTROL_FLOW || e.kind == PDGEdge.Kind.CONTROL_FLOW_EXC) { final Node from = pdg2cfg.get(e.from); final Node to = pdg2cfg.get(e.to); addEdge(from, to); } } }
private static SDGNode convertNode(SDGBuilder sdg, PDGNode node) { Operation op = null; Kind kind = null; int[] allocNodes = null; switch (node.getKind()) { case ACTUAL_IN: op = Operation.ACTUAL_IN; kind = Kind.ACTUAL_IN; break; case ACTUAL_OUT: op = Operation.ACTUAL_OUT; kind = Kind.ACTUAL_OUT; break; case CALL: op = Operation.CALL; kind = Kind.CALL; if (sdg.cfg.computeInterference) { TIntSet allocNodesAsSet = sdg.getAllocationNodes(node); if (allocNodesAsSet != null) { allocNodes = allocNodesAsSet.toArray(); } } break; case ENTRY: op = Operation.ENTRY; kind = Kind.ENTRY; break; case EXIT: op = Operation.EXIT; kind = Kind.EXIT; break; case EXPRESSION: op = Operation.ASSIGN; kind = Kind.EXPRESSION; break; case FOLDED: op = Operation.COMPOUND; kind = Kind.FOLDED; break; case FORMAL_IN: op = Operation.FORMAL_IN; kind = Kind.FORMAL_IN; break; case FORMAL_OUT: op = Operation.FORMAL_OUT; kind = Kind.FORMAL_OUT; break; case HREAD: op = Operation.REFERENCE; kind = Kind.EXPRESSION; break; case HWRITE: op = Operation.MODIFY; kind = Kind.EXPRESSION; break; case JOIN: op = Operation.COMPOUND; kind = Kind.JOIN; break; case NEW: op = Operation.DECLARATION; kind = Kind.NORMAL; break; case NORMAL: op = Operation.COMPOUND; kind = Kind.NORMAL; break; case PHI: op = Operation.ASSIGN; kind = Kind.EXPRESSION; break; case PREDICATE: op = Operation.IF; kind = Kind.PREDICATE; break; case SYNCHRONIZATION: op = Operation.MONITOR; kind = Kind.SYNCHRONIZATION; break; default: throw new IllegalStateException("Unknown node kind: " + node.getKind().name()); } SourceLocation sloc = node.getSourceLocation(); SDGNode sn = new SecurityNode( node.getId(), op, node.getLabel(), node.getPdgId(), node.getType(), sloc.getSourceFile(), sloc.getStartRow(), sloc.getStartColumn(), sloc.getEndRow(), sloc.getEndColumn(), node.getBytecodeName(), node.getBytecodeIndex()); if (node.getKind() == PDGNode.Kind.ENTRY) { PDG pdg = sdg.getPDGforId(node.getPdgId()); IMethod im = pdg.getMethod(); if (im != null) { IClass cls = im.getDeclaringClass(); if (cls != null) { String clsLoader = cls.getClassLoader().toString(); sn.setClassLoader(clsLoader); } } } if (allocNodes != null) { sn.setAllocationSites(allocNodes); } if (node.getAliasDataSources() != null) { sn.setAliasDataSources(node.getAliasDataSources()); } assert sn.getKind() == kind; return sn; }
private void run(IProgressMonitor progress) throws CancelException { final Map<PDGNode, PDGNode[]> entry2out = new HashMap<PDGNode, PDGNode[]>(); // add out nodes for each non-primitive parameter for (final PDG pdg : sdg.getAllPDGs()) { // primitive types nodes are null final PDGNode[] formOuts = new PDGNode[pdg.params.length]; for (int i = 0; i < pdg.params.length; i++) { final PDGNode formIn = pdg.params[i]; final TypeReference type = pdg.getParamType(i); if (createOutputParamFor(type)) { final PDGNode formOut = pdg.addOutputFieldChildTo( pdg.entry, formIn.getLabel(), formIn.getBytecodeName(), formIn.getBytecodeIndex(), formIn.getTypeRef()); formOuts[i] = formOut; } } entry2out.put(pdg.entry, formOuts); for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actIns = pdg.getParamIn(call); final PDGNode[] actOuts = new PDGNode[actIns.length]; for (int i = 0; i < actIns.length; i++) { final PDGNode actIn = actIns[i]; final TypeReference type = pdg.getParamType(call, i); if (createOutputParamFor(type)) { final PDGNode actOut = pdg.addOutputFieldChildTo( call, actIn.getLabel(), actIn.getBytecodeName(), actIn.getBytecodeIndex(), actIn.getTypeRef()); actOuts[i] = actOut; } } entry2out.put(call, actOuts); } } // connect form-outs of called procedures with act-outs for (final PDG pdg : sdg.getAllPDGs()) { for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actOuts = entry2out.get(call); assert actOuts != null; for (final PDGEdge out : pdg.outgoingEdgesOf(call)) { if (out.kind == PDGEdge.Kind.CALL_STATIC || out.kind == PDGEdge.Kind.CALL_VIRTUAL) { final PDGNode calleeEntry = out.to; final PDGNode[] formOuts = entry2out.get(calleeEntry); final PDG callee = sdg.getPDGforId(calleeEntry.getPdgId()); assert formOuts != null; assert actOuts.length == formOuts.length; for (int i = 0; i < actOuts.length; i++) { final PDGNode actOut = actOuts[i]; if (actOut != null) { // primitive type (and immutable type) params have no act out callee.addVertex(actOut); final PDGNode formOut = formOuts[i]; if (formOut != null) { callee.addEdge(formOut, actOut, PDGEdge.Kind.PARAMETER_OUT); } } } } } } } // collect reachable points-to elements for reachable fields for each parameter for (final PDG pdg : sdg.getAllPDGs()) { final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsMod = new HashMap<PDGNode, OrdinalSet<InstanceKey>>(); final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsRef = new HashMap<PDGNode, OrdinalSet<InstanceKey>>(); final IR ir = pdg.cgNode.getIR(); if (ir == null) { continue; } for (int i = 0; i < pdg.params.length; i++) { if (!pdg.getParamType(i).isPrimitiveType()) { final PDGNode formIn = pdg.params[i]; final int ssaVar = ir.getParameter(i); if (ssaVar >= 0) { final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsMod.put(formIn, ptsSet); } } } final PDGNode[] formOuts = entry2out.get(pdg.entry); for (int i = 0; i < formOuts.length; i++) { final PDGNode formOut = formOuts[i]; if (formOut != null) { final PDGNode formIn = pdg.params[i]; final OrdinalSet<InstanceKey> ptsSet = node2ptsMod.get(formIn); node2ptsRef.put(formOut, ptsSet); } } final TypeReference retType = pdg.getMethod().getReturnType(); if (retType != TypeReference.Void && !retType.isPrimitiveType()) { for (final PDGNode retNode : pdg.getReturns()) { final SSAReturnInstruction ret = (SSAReturnInstruction) pdg.getInstruction(retNode); final int ssaVar = ret.getResult(); final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsRef.put(retNode, ptsSet); } } for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actIns = pdg.getParamIn(call); final SSAAbstractInvokeInstruction invk = (SSAAbstractInvokeInstruction) pdg.getInstruction(call); for (int i = 0; i < actIns.length; i++) { if (!pdg.getParamType(call, i).isPrimitiveType()) { final PDGNode actIn = actIns[i]; final int ssaVar = invk.getUse(i); if (ssaVar >= 0) { final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsRef.put(actIn, ptsSet); } } } final PDGNode actOuts[] = entry2out.get(call); for (int i = 0; i < actIns.length; i++) { final PDGNode actOut = actOuts[i]; if (actOut != null) { final PDGNode actIn = actIns[i]; final OrdinalSet<InstanceKey> ptsSet = node2ptsRef.get(actIn); node2ptsMod.put(actOut, ptsSet); } } final TypeReference callRetType = invk.getDeclaredTarget().getReturnType(); if (callRetType != TypeReference.Void && !callRetType.isPrimitiveType()) { final int ssaVar = invk.getReturnValue(0); final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); final PDGNode retNode = pdg.getReturnOut(call); node2ptsMod.put(retNode, ptsSet); } } // create mod/ref sets for get & set instructions for (final PDGField read : pdg.getFieldReads()) { if (!read.field.isStatic()) { if (read.field.isArray()) { final SSAArrayLoadInstruction ali = (SSAArrayLoadInstruction) pdg.getInstruction(read.node); final int ssaVarBase = ali.getArrayRef(); if (ssaVarBase >= 0) { final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase); node2ptsRef.put(read.accfield, ptsSet); } } else { final SSAGetInstruction get = (SSAGetInstruction) pdg.getInstruction(read.node); final int ssaVarBase = get.getRef(); if (ssaVarBase >= 0) { final IField field = sdg.getClassHierarchy().resolveField(get.getDeclaredField()); final OrdinalSet<InstanceKey> ptsSet = pointsToObjectField(pdg.cgNode, ssaVarBase, field); node2ptsRef.put(read.accfield, ptsSet); } } // final SSAInstruction get = pdg.getInstruction(read.node); // final int ssaVar = get.getDef(); // if (ssaVar >= 0) { // final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); // node2ptsRef.put(read.accfield, ptsSet); // } } } for (final PDGField write : pdg.getFieldWrites()) { if (!write.field.isStatic()) { if (write.field.isArray()) { final SSAArrayStoreInstruction asi = (SSAArrayStoreInstruction) pdg.getInstruction(write.node); final int ssaVarBase = asi.getArrayRef(); if (ssaVarBase >= 0) { final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase); node2ptsMod.put(write.accfield, ptsSet); } } else { final SSAPutInstruction put = (SSAPutInstruction) pdg.getInstruction(write.node); final int ssaVarBase = put.getRef(); if (ssaVarBase >= 0) { final IField field = sdg.getClassHierarchy().resolveField(put.getDeclaredField()); final OrdinalSet<InstanceKey> ptsSet = pointsToObjectField(pdg.cgNode, ssaVarBase, field); node2ptsMod.put(write.accfield, ptsSet); } } } } // add data flow for each pdg FlatHeapParamsDataFlow.compute( pdg, node2ptsMod, node2ptsRef, (sdg.cfg.accessPath ? PDGEdge.Kind.DATA_ALIAS : PDGEdge.Kind.DATA_HEAP), progress); } }