manager.getICFG().getMethodOf(resultAbs.getSinkStmt()).getDeclaringClass().getName())) return true; Abstraction abs = resultAbs.getAbstraction(); abs = abs.deriveNewAbstraction(abs.getAccessPath(), resultAbs.getSinkStmt()); abs.setCorrespondingCallSite(resultAbs.getSinkStmt()); resultAbs = new AbstractionAtSink(resultAbs.getSinkDefinition(), abs, resultAbs.getSinkStmt()); Abstraction newAbs = this.results.putIfAbsentElseGet(resultAbs, resultAbs.getAbstraction()); if (newAbs != resultAbs.getAbstraction()) newAbs.addNeighbor(resultAbs.getAbstraction());
@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; }
@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; }
@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(AbstractionAtSink abs) { return new SourceFindingTask(lastTaskId++, abs, abs.getAbstraction()); }
@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; }
/** * Removes all abstractions from the given set that arrive at the same sink * statement as another abstraction, but cover less tainted variables. If, e.g., * a.b.* and a.* arrive at the same sink, a.b.* is already covered by a.* and * can thus safely be removed. * * @param res The result set from which to remove all entailed abstractions */ private void removeEntailedAbstractions(Set<AbstractionAtSink> res) { for (Iterator<AbstractionAtSink> absAtSinkIt = res.iterator(); absAtSinkIt.hasNext();) { AbstractionAtSink curAbs = absAtSinkIt.next(); for (AbstractionAtSink checkAbs : res) { if (checkAbs != curAbs && checkAbs.getSinkStmt() == curAbs.getSinkStmt() && checkAbs.getAbstraction().isImplicit() == curAbs.getAbstraction().isImplicit() && checkAbs.getAbstraction().getSourceContext() == curAbs.getAbstraction().getSourceContext()) { if (checkAbs.getAbstraction().getAccessPath().entails(curAbs.getAbstraction().getAccessPath())) { absAtSinkIt.remove(); break; } } } } }
@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 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()); } }
if (triggerComputationForNeighbors() && abs.getAbstraction().getNeighbors() != null) { for (Abstraction neighbor : abs.getAbstraction().getNeighbors()) { AbstractionAtSink neighborAtSink = new AbstractionAtSink(abs.getSinkDefinition(), neighbor, abs.getSinkStmt()); task = getTaintPathTask(neighborAtSink); if (task != null)
pathBuilder.reset(); pathBuilder.computeTaintPaths( Collections.singleton(new AbstractionAtSink(null, a, a.getCurrentStmt())));
@Override public void run() { while (!abstractionQueue.isEmpty()) { // Terminate the thread when we run out of memory if (isKilled()) { abstractionQueue.clear(); return; } Abstraction abstraction = abstractionQueue.remove(0); if (abstraction.getSourceContext() != null) { // Register the result results.addResult(flagAbs.getSinkDefinition(), flagAbs.getAbstraction().getAccessPath(), flagAbs.getSinkStmt(), abstraction.getSourceContext().getDefinition(), abstraction.getSourceContext().getAccessPath(), abstraction.getSourceContext().getStmt(), abstraction.getSourceContext().getUserData(), null); // Sources may not have predecessors assert abstraction.getPredecessor() == null; } else if (abstraction.getPredecessor().registerPathFlag(taskId, numTasks)) abstractionQueue.add(abstraction.getPredecessor()); if (abstraction.getNeighbors() != null) for (Abstraction nb : abstraction.getNeighbors()) if (nb.registerPathFlag(taskId, numTasks)) abstractionQueue.add(nb); } } }
/** * Checks whether the given taint abstraction at the given satement triggers a * sink. If so, a new result is recorded * * @param d1 The context abstraction * @param source The abstraction that has reached the given statement * @param stmt The statement that was reached * @param retVal The value to check */ private void checkForSink(Abstraction d1, Abstraction source, Stmt stmt, final Value retVal) { // The incoming value may be a complex expression. We have to look at // every simple value contained within it. for (Value val : BaseSelector.selectBaseList(retVal, false)) { final AccessPath ap = source.getAccessPath(); final ISourceSinkManager sourceSinkManager = getManager().getSourceSinkManager(); if (ap != null && sourceSinkManager != null && source.isAbstractionActive() && getAliasing().mayAlias(val, ap.getPlainValue())) { SinkInfo sinkInfo = sourceSinkManager.getSinkInfo(stmt, getManager(), source.getAccessPath()); if (sinkInfo != null && !getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, stmt))) killState = true; } } }
@Override public Collection<Abstraction> propagateCallToReturnFlow(Abstraction d1, Abstraction source, Stmt stmt, ByReferenceBoolean killSource, ByReferenceBoolean killAll) { // We only report leaks for active taints, not for alias queries if (source.isAbstractionActive() && !source.getAccessPath().isStaticFieldRef()) { // Is the taint even visible inside the callee? if (!stmt.containsInvokeExpr() || isTaintVisibleInCallee(stmt, source)) { // Is this a sink? if (getManager().getSourceSinkManager() != null) { // Get the sink descriptor SinkInfo sinkInfo = getManager().getSourceSinkManager().getSinkInfo(stmt, getManager(), source.getAccessPath()); // If we have already seen the same taint at the same sink, there is no need to // propagate this taint any further. if (sinkInfo != null && !getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, stmt))) { killState = true; } } } } // If we are in the kill state, we stop the analysis if (killAll != null) killAll.value |= killState; return null; }
@Override public Collection<Abstraction> propagateReturnFlow(Collection<Abstraction> callerD1s, Abstraction source, Stmt stmt, Stmt retSite, Stmt callSite, ByReferenceBoolean killAll) { // Check whether this return is treated as a sink if (stmt instanceof ReturnStmt) { final ReturnStmt returnStmt = (ReturnStmt) stmt; boolean matches = source.getAccessPath().isLocal() || source.getAccessPath().getTaintSubFields(); if (matches && source.isAbstractionActive() && getManager().getSourceSinkManager() != null && getAliasing().mayAlias(source.getAccessPath().getPlainValue(), returnStmt.getOp())) { SinkInfo sinkInfo = getManager().getSourceSinkManager().getSinkInfo(returnStmt, getManager(), source.getAccessPath()); if (sinkInfo != null && !getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, returnStmt))) killState = true; } } // If we are in the kill state, we stop the analysis if (killAll != null) killAll.value |= killState; return null; }
SinkInfo sinkInfo = getManager().getSourceSinkManager().getSinkInfo(stmt, getManager(), null); if (sinkInfo != null) getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, stmt)); } else { SootMethod curMethod = getManager().getICFG().getMethodOf(stmt); SinkInfo sinkInfo = getManager().getSourceSinkManager().getSinkInfo(stmt, getManager(), null); if (sinkInfo != null) getResults().addResult(new AbstractionAtSink(sinkInfo.getDefinition(), source, stmt));