/** * Extends the taint propagation path with the given abstraction * * @param abs The abstraction to put on the taint propagation path * @return The new taint propagation path If this path would contain a loop, * null is returned instead of the looping path. */ public SourceContextAndPath extendPath(Abstraction abs) { return extendPath(abs, null); }
@Override public void run() { Stack<Pair<Stmt, Set<Abstraction>>> initialStack = new Stack<Pair<Stmt, Set<Abstraction>>>(); initialStack.push(new Pair<Stmt, Set<Abstraction>>(null, Collections.newSetFromMap(new IdentityHashMap<Abstraction, Boolean>()))); for (SourceContextAndPath context : getPaths(lastTaskId++, abs.getAbstraction(), initialStack)) { results.addResult(abs.getSinkDefinition(), abs.getAbstraction().getAccessPath(), abs.getSinkStmt(), context.getDefinition(), context.getAccessPath(), context.getStmt(), context.getUserData(), context.getAbstractionPath()); } }
@Override public SourceContextAndPath clone() { final SourceContextAndPath scap = new SourceContextAndPath(definition, accessPath, stmt, userData); if (path != null) scap.path = new ExtensibleList<Abstraction>(this.path); if (callStack != null) scap.callStack = new ExtensibleList<Stmt>(callStack); return scap; }
@Override public void runIncrementalPathCompuation() { Set<AbstractionAtSink> incrementalAbs = new HashSet<>(); for (Abstraction abs : pathCache.keySet()) for (SourceContextAndPath scap : pathCache.get(abs)) { if (abs.getNeighbors() != null && abs.getNeighbors().size() != scap.getNeighborCounter()) { // This is a path for which we have to process the new // neighbors scap.setNeighborCounter(abs.getNeighbors().size()); for (Abstraction neighbor : abs.getNeighbors()) incrementalAbs.add(new AbstractionAtSink(scap.getDefinition(), neighbor, scap.getStmt())); } } if (!incrementalAbs.isEmpty()) this.computeTaintPaths(incrementalAbs); }
@Override protected boolean checkForSource(Abstraction abs, SourceContextAndPath scap) { // Record the abstraction visitedAbstractions.add(abs); // Source abstractions do not have predecessors if (abs.getPredecessor() != null) return false; // Save the abstraction path SummarySourceContextAndPath sscap = (SummarySourceContextAndPath) scap; SummarySourceInfo ssi = new SummarySourceInfo(abs.getSourceContext().getAccessPath(), abs.getSourceContext().getStmt(), abs.getSourceContext().getUserData(), sscap.getCurrentAccessPath(), sscap.getIsAlias(), !scap.isCallStackEmpty() || sscap.getDepth() != 0); ResultSinkInfo rsi = new ResultSinkInfo(null, scap.getAccessPath(), scap.getStmt()); this.resultInfos.add(new SummaryResultInfo(ssi, rsi)); return true; }
@Override protected Runnable getTaintPathTask(final AbstractionAtSink abs) { SourceContextAndPath scap = new SourceContextAndPath(abs.getSinkDefinition(), abs.getAbstraction().getAccessPath(), abs.getSinkStmt()); scap = scap.extendPath(abs.getAbstraction(), pathConfig); if (pathCache.put(abs.getAbstraction(), scap)) if (!checkForSource(abs.getAbstraction(), scap)) return new SourceFindingTask(abs.getAbstraction()); return null; }
SourceContextAndPath extendedScap = scap.extendPath(pred, pathConfig); if (extendedScap == null) return false; SourceContextAndPath extendedScap = scap.extendPath(pred, pathConfig); if (extendedScap == null) return false; Pair<SourceContextAndPath, Stmt> pathAndItem = extendedScap.popTopCallStackItem(); if (pathAndItem != null) { Stmt topCallStackItem = pathAndItem.getO2();
/** * Pops the top item off the call stack. * * @return The new {@link SourceContextAndPath} object as the first element of * the pair and the call stack item that was popped off as the second * element. If there is no call stack, null is returned. */ public Pair<SourceContextAndPath, Stmt> popTopCallStackItem() { if (callStack == null || callStack.isEmpty()) return null; SourceContextAndPath scap = clone(); Stmt lastStmt = null; Object c = scap.callStack.removeLast(); if (c instanceof ExtensibleList) { lastStmt = scap.callStack.getLast(); scap.callStack = (ExtensibleList<Stmt>) c; } else lastStmt = (Stmt) c; if (scap.callStack.isEmpty()) scap.callStack = null; return new Pair<>(scap, lastStmt); }
@Override public String toString() { return super.toString() + "\n\ton Path: " + getAbstractionPath(); } }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; SummarySourceContextAndPath other = (SummarySourceContextAndPath) obj; if (callees == null) { if (other.callees != null) return false; } else if (!callees.equals(other.callees)) return false; if (manager == null) { if (other.manager != null) return false; } else if (!manager.equals(other.manager)) return false; if (curAP == null) { if (other.curAP != null) return false; } else if (!curAP.equals(other.curAP)) return false; if (isAlias != other.isAlias) return false; // We deliberately ignore the depth to avoid infinite progression into // recursive method calls return true; }
@Override public void runIncrementalPathCompuation() { Set<AbstractionAtSink> incrementalAbs = new HashSet<>(); for (Abstraction abs : pathCache.keySet()) for (SourceContextAndPath scap : pathCache.get(abs)) { if (abs.getNeighbors() != null && abs.getNeighbors().size() != scap.getNeighborCounter()) { // This is a path for which we have to process the new // neighbors scap.setNeighborCounter(abs.getNeighbors().size()); for (Abstraction neighbor : abs.getNeighbors()) incrementalAbs.add(new AbstractionAtSink(scap.getDefinition(), neighbor, scap.getStmt())); } } if (!incrementalAbs.isEmpty()) this.computeTaintPaths(incrementalAbs); }
@Override protected Runnable getTaintPathTask(final AbstractionAtSink abs) { SourceContextAndPath scap = new SourceContextAndPath(abs.getSinkDefinition(), abs.getAbstraction().getAccessPath(), abs.getSinkStmt()); scap = scap.extendPath(abs.getAbstraction(), pathConfig); if (pathCache.put(abs.getAbstraction(), scap)) if (!checkForSource(abs.getAbstraction(), scap)) return new SourceFindingTask(abs.getAbstraction()); return null; }
/** * Checks whether the given abstraction is a source. If so, a result entry is * created. * * @param abs * The abstraction to check * @param scap * The path leading up to the current abstraction * @return True if the current abstraction is a source, otherwise false */ private boolean checkForSource(Abstraction abs, SourceContextAndPath scap) { if (abs.getPredecessor() != null) return false; // If we have no predecessors, this must be a source assert abs.getSourceContext() != null; assert abs.getNeighbors() == null; // Register the source that we have found SourceContext sourceContext = abs.getSourceContext(); results.addResult(scap.getDefinition(), scap.getAccessPath(), scap.getStmt(), sourceContext.getDefinition(), sourceContext.getAccessPath(), sourceContext.getStmt(), sourceContext.getUserData(), scap.getAbstractionPath()); return true; }
SourceContextAndPath sourceAndPath = new SourceContextAndPath(curAbs.getSourceContext().getDefinition(), curAbs.getSourceContext().getAccessPath(), curAbs.getSourceContext().getStmt(), curAbs.getSourceContext().getUserData()).extendPath(curAbs); cacheData.add(sourceAndPath); SourceContextAndPath extendedPath = curScap.extendPath(curAbs, pathConfig); if (extendedPath != null) cacheData.add(extendedPath);
private boolean processPredecessor(SourceContextAndPath scap, Abstraction pred) { // Put the current statement on the list SourceContextAndPath extendedScap = scap.extendPath(pred, pathConfig); if (extendedScap == null) return false; // Add the new path checkForSource(pred, extendedScap); final int maxPaths = pathConfig.getMaxPathsPerAbstraction(); if (maxPaths > 0) { Set<SourceContextAndPath> existingPaths = pathCache.get(pred); if (existingPaths != null && existingPaths.size() > maxPaths) return false; } return pathCache.put(pred, extendedScap); }
/** * Checks whether the given abstraction is a source. If so, a result entry is * created. * * @param abs The abstraction to check * @param scap The path leading up to the current abstraction * @return True if the current abstraction is a source, otherwise false */ protected boolean checkForSource(Abstraction abs, SourceContextAndPath scap) { if (abs.getPredecessor() != null) return false; // If we have no predecessors, this must be a source assert abs.getSourceContext() != null; // A source should normally never have neighbors, but it can happen // with ICCTA if (abs.getNeighbors() != null) { // we ignore this issue for now, because the neighbor's source // contexts seem to be equal to our own one } // Register the source that we have found SourceContext sourceContext = abs.getSourceContext(); Pair<ResultSourceInfo, ResultSinkInfo> newResult = results.addResult(scap.getDefinition(), scap.getAccessPath(), scap.getStmt(), sourceContext.getDefinition(), sourceContext.getAccessPath(), sourceContext.getStmt(), sourceContext.getUserData(), scap.getAbstractionPath()); // Notify our handlers if (resultAvailableHandlers != null) for (OnPathBuilderResultAvailable handler : resultAvailableHandlers) handler.onResultAvailable(newResult.getO1(), newResult.getO2()); return true; }
@Override protected Runnable getTaintPathTask(AbstractionAtSink abs) { SourceContextAndPath scap = new SummarySourceContextAndPath(manager, abs.getAbstraction().getAccessPath(), abs.getSinkStmt(), AliasUtils.canAccessPathHaveAliases(abs.getAbstraction().getAccessPath()), abs.getAbstraction().getAccessPath(), new ArrayList<SootMethod>(), context); scap = scap.extendPath(abs.getAbstraction()); if (scap != null) { if (pathCache.put(abs.getAbstraction(), scap)) if (!checkForSource(abs.getAbstraction(), scap)) return new SourceFindingTask(abs.getAbstraction()); } return null; }