private static SDGNode findExitNode(SDGNode node, CFG cfg) { SDGNode entry = cfg.getEntry(node); LinkedList<SDGNode> wl = new LinkedList<SDGNode>(); Set<SDGNode> visited = new HashSet<SDGNode>(); wl.add(entry); while (!wl.isEmpty()) { SDGNode n = wl.poll(); visited.add(n); if (n.getKind() == SDGNode.Kind.EXIT) { return n; } else { for (SDGEdge e : cfg.outgoingEdgesOf(n)) { if (!visited.contains(e.getTarget()) && e.getKind() == SDGEdge.Kind.CONTROL_FLOW) { wl.add(e.getTarget()); } } } } throw new IllegalStateException( "Visited the following nodes, which not include an exit node: " + visited); }
protected SDGNode reachedNode(SDGEdge edge) { return edge.getSource(); }
@Override public Collection<SDGNode> slice(Collection<SDGNode> criteria) { LinkedList<SDGNode> worklist_0 = new LinkedList<SDGNode>(); LinkedList<SDGNode> worklist_1 = new LinkedList<SDGNode>(); LinkedList<SDGNode> worklist_2 = new LinkedList<SDGNode>(); HashSet<SDGNode> visited_0_1 = new HashSet<SDGNode>(); HashSet<SDGNode> visited_2 = new HashSet<SDGNode>(); worklist_0.addAll(criteria); visited_0_1.addAll(criteria); // System.out.println("searching for data channels"); edgeListener.init(); // die basis bildet ein iterierter zwei-phasen slice while (!worklist_0.isEmpty()) { // init the next iteration visited_2.clear(); worklist_1.add(worklist_0.poll()); visited_0_1.add(worklist_1.peek()); // === phase 1 === // only ascend to calling procedures while (!worklist_1.isEmpty()) { SDGNode next = worklist_1.poll(); for (SDGEdge edge : g.incomingEdgesOf(next)) { edgeListener.edgeEncountered(edge); SDGNode adjacent = edge.getSource(); if (edge.getKind() == SDGEdge.Kind.INTERFERENCE || edge.getKind() == SDGEdge.Kind.FORK_IN || edge.getKind() == SDGEdge.Kind.FORK_OUT || edge.getKind() == SDGEdge.Kind.FORK) { // handle thread edges - concurrency edges have to be // traversed in the next iteration // TODO: what about join edges? Why are thread numbers // not taken into account? // I suspect that this is not critical for correctness // but rather for precision... if (visited_0_1.add(adjacent)) { worklist_0.add(adjacent); } } else if (edge.getKind() == SDGEdge.Kind.PARAMETER_OUT) { // descend into called procedure in phase two! if (visited_2.add(adjacent)) { worklist_2.add(adjacent); } } else if (edge.getKind().isSDGEdge()) { // note that return // edges are no // sdg edges! // intra-procedural or ascending edge if (visited_0_1.add(adjacent)) { worklist_1.add(adjacent); } } } } // === phase 2 === // visit all procedures called underway while (!worklist_2.isEmpty()) { SDGNode next = worklist_2.poll(); for (SDGEdge edge : g.incomingEdgesOf(next)) { edgeListener.edgeEncountered(edge); SDGNode adjacent = edge.getSource(); if (edge.getKind() == SDGEdge.Kind.INTERFERENCE) { // handle interference edges: create new elements for // worklist_0 if (visited_0_1.add(adjacent)) { worklist_0.add(adjacent); } } else if (edge.getKind().isSDGEdge() && edge.getKind() != SDGEdge.Kind.CALL && edge.getKind() != SDGEdge.Kind.PARAMETER_IN && edge.getKind() != SDGEdge.Kind.FORK && edge.getKind() != SDGEdge.Kind.FORK_IN) { // intra-procedural or param-out edge if (visited_2.add(adjacent)) { worklist_2.add(adjacent); } } } } } return visited_0_1; }
private static Set<SDGNode> filterStatic(final SDG sdg, final Set<SDGNode> nodes) { final Set<SDGNode> filtered = new HashSet<SDGNode>(); for (SDGNode n : nodes) { if (n.getBytecodeIndex() == BytecodeLocation.ROOT_PARAMETER) { filtered.add(n); } } LinkedList<SDGNode> work = new LinkedList<SDGNode>(); work.addAll(filtered); while (!work.isEmpty()) { final SDGNode n = work.removeFirst(); for (SDGEdge edge : sdg.getOutgoingEdgesOfKind(n, SDGEdge.Kind.PARAMETER_STRUCTURE)) { final SDGNode tgt = edge.getTarget(); if (!filtered.contains(tgt)) { filtered.add(tgt); work.add(tgt); } } } return filtered; }