Abstraction pred = output.getPredecessor(); if (pred != null && pred != input) output.setPredecessor(input); if (input.equals(output)) { if (output.getCurrentStmt() == null || input.getCurrentStmt() == output.getCurrentStmt()) return input; if (input.getCurrentStmt() == null) { synchronized (input) { if (input.getCurrentStmt() == null) { input.setCurrentStmt(output.getCurrentStmt()); input.setCorrespondingCallSite(output.getCorrespondingCallSite()); return input; AccessPath newAP = getCachedAccessPath(output.getAccessPath()); output.setAccessPath(newAP); Abstraction curAbs = output.getPredecessor(); while (curAbs != null && curAbs.getNeighbors() == null) { Abstraction predPred = curAbs.getPredecessor(); if (predPred != null) { if (predPred.equals(output)) output = predPred;
protected Abstraction deriveNewAbstractionMutable(AccessPath p, Stmt currentStmt) { // An abstraction needs an access path if (p == null) return null; if (this.accessPath.equals(p) && this.currentStmt == currentStmt) { Abstraction abs = clone(); abs.currentStmt = currentStmt; return abs; } Abstraction abs = new Abstraction(p, this); abs.predecessor = this; abs.currentStmt = currentStmt; abs.propagationPathLength = propagationPathLength + 1; if (!abs.getAccessPath().isEmpty()) abs.postdominators = null; if (!abs.isAbstractionActive()) abs.dependsOnCutAP = abs.dependsOnCutAP || p.isCutOffApproximation(); abs.sourceContext = null; return abs; }
/** * Adds the given abstraction and statement to the result map * * @param abs * The abstraction to be collected * @param stmt * The statement at which the abstraction was collected */ protected void addResult(Abstraction abs, Stmt stmt) { // Add the abstraction to the map. If we already have an equal // abstraction, we must add the current one as a neighbor. if (!this.result.put(abs, stmt)) { for (Abstraction abs2 : result.keySet()) { if (abs.equals(abs2)) { abs2.addNeighbor(abs); break; } } } }
@Override public Abstraction clone() { Abstraction abs = new Abstraction(accessPath, this); abs.predecessor = this; abs.neighbors = null; abs.currentStmt = null; abs.correspondingCallSite = null; abs.propagationPathLength = propagationPathLength + 1; assert abs.equals(this); return abs; }
public Abstraction getActiveCopy() { if (this.isAbstractionActive()) return this; Abstraction a = clone(); a.sourceContext = null; a.activationUnit = null; return a; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * abs.hashCode(); result = prime * result + ((abs.getPredecessor() == null) ? 0 : abs.getPredecessor().hashCode()); result = prime * result + ((abs.getCurrentStmt() == null) ? 0 : abs.getCurrentStmt().hashCode()); result = prime * result + ((abs.getCorrespondingCallSite() == null) ? 0 : abs.getCorrespondingCallSite().hashCode()); return result; }
@Override public boolean isExclusive(Stmt stmt, Abstraction taintedPath) { if (isExclusiveInternal(stmt, taintedPath.getAccessPath())) { wrapperHits.incrementAndGet(); return true; } else { wrapperMisses.incrementAndGet(); return false; } }
@Override public Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstraction taintedPath) { // Compute the tainted access paths Set<AccessPath> aps = getTaintsForMethodInternal(stmt, taintedPath.getAccessPath()); if (aps == null || aps.isEmpty()) return null; // Convert the access paths into full abstractions Set<Abstraction> res = new HashSet<Abstraction>(aps.size()); for (AccessPath ap : aps) if (ap == taintedPath.getAccessPath()) res.add(taintedPath); else res.add(taintedPath.deriveNewAbstraction(ap, stmt)); return res; }
if (abs.getCurrentStmt() == null && abs.getCorrespondingCallSite() == null) return this; if (abs.getSourceContext() != null) return this; if (abs.getCorrespondingCallSite() != null && abs.getCorrespondingCallSite() != abs.getCurrentStmt()) { if (scap.callStack == null) scap.callStack = new ExtensibleList<Stmt>(); else if (!scap.callStack.isEmpty() && scap.callStack.getFirstSlow() == abs.getCorrespondingCallSite()) return null; scap.callStack = scap.callStack.add(abs.getCorrespondingCallSite()); final Stmt stmt = abs.getCurrentStmt(); final Stmt callSite = abs.getCorrespondingCallSite(); boolean matched = false; if (stmt == null && abs.getSourceContext() != null) { scap.curAP = abs.getSourceContext().getAccessPath(); scap.validate(); return scap; if (abs.getCorrespondingCallSite() != abs.getCurrentStmt()) { Pair<SourceContextAndPath, Stmt> pathAndItem = scap.popTopCallStackItem(); if (pathAndItem != null) { Stmt topCallStackItem = pathAndItem.getO2(); if (topCallStackItem != abs.getCurrentStmt()) return null;
if (source.isAbstractionActive()) { if(call.getInvokeExpr().getMethod().getSignature().equals(SIG_ARRAYCOPY)) { if(params[0].equals(source.getAccessPath().getPlainValue())) { if (manager.getTypeUtils().checkCast(source.getAccessPath(), params[2].getType())) { AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(), params[2], source.getAccessPath().getBaseType(), false); Abstraction abs = source.deriveNewAbstraction(ap, call); abs.setCorrespondingCallSite(call); return Collections.singleton(abs); if(params[1].equals(source.getAccessPath().getPlainValue())) { if (manager.getTypeUtils().checkCast(source.getAccessPath(), params[1].getType())) { AccessPath ap = manager.getAccessPathFactory().copyWithNewValue(source.getAccessPath(), params[1], source.getAccessPath().getBaseType(), false, true, ArrayTaintType.Length); Abstraction abs = source.deriveNewAbstraction(ap, call); abs.setCorrespondingCallSite(call); return Collections.singleton(abs);
boolean implicitTaint = newSource.getTopPostdominator() != null && newSource.getTopPostdominator().getUnit() != null; implicitTaint |= newSource.getAccessPath().isEmpty(); if ((d1 == null || d1.getAccessPath().isEmpty()) && !(leftValue instanceof FieldRef)) return Collections.singleton(newSource); if (newSource.getAccessPath().isEmpty()) addLeftValue = true; boolean aliasOverwritten = !addLeftValue && !newSource.isAbstractionActive() && Aliasing.baseMatchesStrict(rightValue, newSource) && rightValue.getType() instanceof RefType && !newSource.dependsOnCutAP(); AccessPath mappedAP = newSource.getAccessPath(); Type targetType = null; if (!addLeftValue && !aliasOverwritten) { mappedAP = aliasing.mayAlias(newSource.getAccessPath(), rightRef); Local sourceBase = newSource.getAccessPath().getPlainValue(); final SootField rightField = rightRef.getField(); && mappedAP.getFirstField() == rightField); } else if (aliasing.mayAlias(rightBase, sourceBase) && newSource.getAccessPath().getFieldCount() == 0 && newSource.getAccessPath().getTaintSubFields()) { addLeftValue = true; targetType = rightField.getType();
if (!source.isAbstractionActive() && source.getCurrentStmt() == stmt) return null; if (source.getPredecessor() != null && !source.getPredecessor().isAbstractionActive() && source.isAbstractionActive() && source.getPredecessor().getActivationUnit() == stmt && source.getAccessPath().equals(source.getPredecessor().getAccessPath())) return null; if (source.getAccessPath().isInstanceFieldRef()) { InstanceFieldRef leftRef = (InstanceFieldRef) assignStmt.getLeftOp(); boolean baseAliases; if (source.isAbstractionActive()) baseAliases = getAliasing().mustAlias((Local) leftRef.getBase(), source.getAccessPath().getPlainValue(), assignStmt); else baseAliases = leftRef.getBase() == source.getAccessPath().getPlainValue(); if (baseAliases) { if (getAliasing().mustAlias(leftRef.getField(), source.getAccessPath().getFirstField())) { killAll.value = true; return null; if (getAliasing().mustAlias((Local) assignStmt.getLeftOp(), source.getAccessPath().getPlainValue(), stmt)) { killAll.value = true; else if (source.getAccessPath().isStaticFieldRef()) { if (assignStmt.getLeftOp() instanceof StaticFieldRef && getAliasing().mustAlias( ((StaticFieldRef) assignStmt.getLeftOp()).getField(), source.getAccessPath().getFirstField())) {
@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); } } }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AbstractionCacheKey other = (AbstractionCacheKey) obj; if (!abs.equals(other.abs)) return false; if (abs.getPredecessor() != other.abs.getPredecessor()) return false; if (abs.getCurrentStmt() != other.abs.getCurrentStmt()) return false; if (abs.getCorrespondingCallSite() != other.abs.getCorrespondingCallSite()) return false; return true; }
if (curAbs.getSourceContext() != null) { SourceContextAndPath sourceAndPath = new SourceContextAndPath(curAbs.getSourceContext().getDefinition(), curAbs.getSourceContext().getAccessPath(), curAbs.getSourceContext().getStmt(), curAbs.getSourceContext().getUserData()).extendPath(curAbs); cacheData.add(sourceAndPath); assert curAbs.getPredecessor() == null; } else { if (curAbs.getCorrespondingCallSite() != null/* newCallStack.push(new Pair<Stmt, Set<Abstraction>>(curAbs.getCorrespondingCallSite(), Collections.newSetFromMap(new IdentityHashMap<Abstraction, Boolean>()))); boolean isMethodEnter = curAbs.getCurrentStmt() != null && curAbs.getCurrentStmt().containsInvokeExpr(); Pair<Stmt, Set<Abstraction>> newStackTop = newCallStack.isEmpty() ? null : newCallStack.peek(); if (newStackTop != null && newStackTop.getO1() != null) { if (curAbs.getCurrentStmt() != newStackTop.getO1()) scanPreds = false; newCallStack.pop(); for (SourceContextAndPath curScap : getPaths(taskId, curAbs.getPredecessor(), newCallStack)) { SourceContextAndPath extendedPath = curScap.extendPath(curAbs, pathConfig); if (extendedPath != null) if (curAbs.getNeighbors() != null) for (Abstraction nb : curAbs.getNeighbors())
Set<Taint> taintsFromAP = createTaintFromAccessPathOnCall(taintedAbs.getAccessPath(), stmt, true); if (taintsFromAP == null || taintsFromAP.isEmpty()) return Collections.emptySet(); resAbs.add(taintedAbs); for (AccessPath ap : res) { Abstraction newAbs = taintedAbs.deriveNewAbstraction(ap, stmt); newAbs.setCorrespondingCallSite(stmt); resAbs.add(newAbs);
abs = abs.deriveNewAbstraction(abs.getAccessPath(), resultAbs.getSinkStmt()); abs.setCorrespondingCallSite(resultAbs.getSinkStmt()); Abstraction newAbs = this.results.putIfAbsentElseGet(resultAbs, resultAbs.getAbstraction()); if (newAbs != resultAbs.getAbstraction()) newAbs.addNeighbor(resultAbs.getAbstraction());
output.setCurrentStmt(null); output.setCorrespondingCallSite(null); && output.getCorrespondingCallSite() == output.getCurrentStmt()) { output.setCurrentStmt(null); output.setCorrespondingCallSite(null); && output.getCorrespondingCallSite() == null && output.getCurrentStmt() != null) { if (output.getCorrespondingCallSite() == null && output.getCurrentStmt() != null && !output.getCurrentStmt().containsInvokeExpr() && !(output.getCurrentStmt() instanceof ReturnStmt) && !(output.getCurrentStmt() instanceof ReturnVoidStmt)) { output.setCurrentStmt(null); output.setCorrespondingCallSite(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; }
/** * Creates a continuation at a gap. A continuation is a new abstraction without * a predecessor that has the gap definition as its source. * * @param source * The source abstraction that flowed into the gap * @param accessPath * The new acces path that shall be tainted after the gap * @param gap * @param stmt * @return */ private Abstraction getContinuation(Abstraction source, AccessPath accessPath, GapDefinition gap, Stmt stmt) { // Make sure that we don't break anything Abstraction newOutAbs = source.clone().deriveNewAbstraction(accessPath, stmt); // Create the source information pointing to the gap. This may not be unique newOutAbs.setPredecessor(null); // If no longer have a predecessor, we must fake a source context newOutAbs.setSourceContext(new SourceContext(null, accessPath, stmt, getFlowSource(accessPath, stmt, gap))); return newOutAbs; }