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); } }