diff --git a/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Main.java b/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Main.java index d5f7c2e..f38a07f 100644 --- a/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Main.java +++ b/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Main.java @@ -47,10 +47,9 @@ private static void runSecucheckAnalysis(SecucheckAnalysis secucheckAnalysis) secucheckAnalysis.setApplicationClassPath(getAppClassPath()); secucheckAnalysis.setSootClassPathJars(getSootClassPath()); - //runDemoSet1(secucheckAnalysis, resultListener); + runDemoSet1(secucheckAnalysis, resultListener); runDemoSet2(secucheckAnalysis, resultListener); - //runDemoSet3(secucheckAnalysis, resultListener); - //runDemoSet4(secucheckAnalysis, resultListener); + runDemoSet3(secucheckAnalysis, resultListener); } @@ -121,16 +120,10 @@ private static void runDemoSet2(SecucheckAnalysis secucheckAnalysis, runAnalysisQuery(secucheckAnalysis, compositeOfTenth, 10, null); } - private static void runDemoSet3(SecucheckAnalysis secucheckAnalysis, - AnalysisResultListener resultListener) throws Exception { - - } - - /** Demo-set X: TODO: Fix the number. + /** Demo-set 3: * - Demonstrates multiple composites - * - Demonstrates the result listener */ - private static void runDemoSet4(SecucheckAnalysis secucheckAnalysis, + private static void runDemoSet3(SecucheckAnalysis secucheckAnalysis, AnalysisResultListener resultListener) throws Exception { List compositeOfFirst = Utility.getInList( @@ -290,11 +283,17 @@ private static String getSootClassPath() { private static List getEntryPoints(){ List entryPoints = new ArrayList(); + EntryPoint entryPoint = new EntryPoint(); entryPoint.setCanonicalClassName("AnalyzeMeLevel1"); entryPoint.setAllMethods(true); entryPoints.add(entryPoint); + + entryPoint = new EntryPoint(); + entryPoint.setCanonicalClassName("AnalyzeMeLevel2"); + entryPoint.setAllMethods(true); + entryPoints.add(entryPoint); + return entryPoints; } - } diff --git a/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Utility.java b/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Utility.java index 3e2e306..bee260d 100644 --- a/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Utility.java +++ b/de.fraunhofer.iem.secucheck.analysis.sample/src/main/java/de/fraunhofer/iem/secucheck/analysis/sample/Utility.java @@ -57,7 +57,7 @@ private static MethodImpl getSanitizerMethod(String canonicalClassName) { List inputs = new ArrayList(); inputs.add(input); - List outputs = null; + List outputs = new ArrayList(); ReturnValue returnValue = null; MethodImpl method = new MethodImpl(); @@ -76,8 +76,8 @@ private static MethodImpl getPropogatorMethod(String canonicalClassName) { List inputs = new ArrayList(); inputs.add(input); - List outputs = null; - ReturnValue returnValue = null; + List outputs = new ArrayList(); + ReturnValue returnValue = new ReturnValue(); MethodImpl method = new MethodImpl(); method.setName("propogator"); @@ -95,7 +95,7 @@ private static MethodImpl getSinkMethod(String canonicalClassName) { List inputs = new ArrayList(); inputs.add(input); - List outputs = null; + List outputs = new ArrayList(); ReturnValue returnValue = null; MethodImpl method = new MethodImpl(); @@ -115,9 +115,9 @@ public static MethodImpl getUsageSourceParameMethod(String canonicalClassName, ReturnValue returnValue = null; // For the first input parameter. - InputParameter inputParam = new InputParameter(); - inputParam.setNumber(0); - inputs.add(inputParam); + OutputParameter outputParam = new OutputParameter(); + outputParam.setNumber(0); + outputs.add(outputParam); MethodImpl method = new MethodImpl(); method.setName("getSecret"); diff --git a/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowAnalysis.java b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowAnalysis.java index 654b033..58b9986 100644 --- a/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowAnalysis.java +++ b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowAnalysis.java @@ -69,39 +69,91 @@ public SingleFlowAnalysis(TaintFlowQueryImpl singleFlow, @Override public AnalysisResult run() { TaintFlowQueryResult result = new TaintFlowQueryResult(); + List>> reachMap; - for (TaintFlowQueryImpl flowQuery : getLogicalSubFlows(singleFlow)) { - if (this.resultListener != null && this.resultListener.isCancelled()) { - break; - } - SeedFactory seedFactory = getSeedFactory(flowQuery); - Boomerang boomerang = getBoomerang(seedFactory); - Seeds seeds = computeSeeds(seedFactory); - - if (seeds.getSources().size() != 0 && seeds.getSinks().size() != 0) { - List sanitizers = getSanitizers(flowQuery); - Map oldMethodBodies = new HashMap(); - List>> reachMap = - new ArrayList>>(); - try { - oldMethodBodies = setEmptySootBodies(sanitizers); - reachMap = analyzeInternal(boomerang, flowQuery, seeds.getSources(), - seeds.getSinks()); - } finally { - oldMethodBodies.entrySet().forEach( entry -> - entry.getKey().setActiveBody(entry.getValue())); - } - if (reachMap.size() == 0) { - result.clear(); - break; - } - result.addQueryResultPairs(reachMap); - } + // Propogator-less execution. + if (isPropogatorless(this.singleFlow)) { + reachMap = analyzePlainFlow(singleFlow); + } else { + reachMap = analyzePropogatorFlow(singleFlow); } + + result.addQueryResultPairs(reachMap); return result; } - private List>> analyzeInternal(Boomerang boomerang, + public List>> + analyzePlainFlow(TaintFlowQueryImpl singleFlow){ + + List>> + reachMap = new ArrayList>>(); + + SeedFactory seedFactory = getSeedFactory(singleFlow); + Boomerang boomerang = getBoomerang(seedFactory); + Seeds seeds = computeSeeds(seedFactory); + + if (seeds.getSources().size() != 0 && seeds.getSinks().size() != 0) { + List sanitizers = getSanitizers(singleFlow); + Map oldMethodBodies = new HashMap(); + try { + oldMethodBodies = setEmptySootBodies(sanitizers); + reachMap = analyzeInternal(boomerang, singleFlow, seeds.getSources(), + seeds.getSinks()); + } finally { + oldMethodBodies.entrySet().forEach( entry -> + entry.getKey().setActiveBody(entry.getValue())); + } + } + return reachMap; + } + + public List>> + analyzePropogatorFlow(TaintFlowQueryImpl singleFlow){ + + /* Each occurance of a propogator/desanitizer would break a single + * TaintFlow into two logical TaintFlows, this generates + * these TaintFlows. */ + + TaintFlowQueryImpl newQuery1 = new TaintFlowQueryImpl(), + newQuery2 = new TaintFlowQueryImpl(); + + newQuery1.getFrom().addAll(singleFlow.getFrom()); + if (singleFlow.getNotThrough() != null) + newQuery1.getNotThrough().addAll(singleFlow.getNotThrough()); + newQuery1.getTo().addAll(singleFlow.getThrough()); + newQuery2.getFrom().addAll(singleFlow.getThrough()); + if (singleFlow.getNotThrough() != null) + newQuery2.getNotThrough().addAll(singleFlow.getNotThrough()); + newQuery2.getTo().addAll(singleFlow.getTo()); + + List>> + originalReachMap = + new ArrayList>>(), + reachMap1 = analyzePlainFlow(newQuery1), + reachMap2 = analyzePlainFlow(newQuery2); + + if (reachMap1.size() != 0 && reachMap2.size() != 0) { + for (DifferentTypedPair> + sourcePair : reachMap1) { + for (DifferentTypedPair> + sinkPair : reachMap2) { + if (isSourceAndSinkMatching(sourcePair.getSecond(), sinkPair.getSecond())) { + SameTypedPair stichedPair = + stitchSourceAndSink(sourcePair.getSecond(), sinkPair.getSecond()); + + originalReachMap.add(new + DifferentTypedPair> + (singleFlow, stichedPair)); + } + } + } + } + + return originalReachMap; + } + + private List>> + analyzeInternal(Boomerang boomerang, TaintFlowQueryImpl partialFlow, Set sources, Set sinks) { @@ -121,39 +173,6 @@ private List getLogicalSubFlows( - TaintFlowQueryImpl partialFlow) { - List subFlows = new ArrayList(); - if (partialFlow.getThrough() == null || partialFlow.getThrough().size() == 0){ - subFlows.add(partialFlow); - return subFlows; - } - - for (MethodImpl propogator : partialFlow.getThrough()) { - TaintFlowQueryImpl newQuery1 = new TaintFlowQueryImpl(), - newQuery2 = new TaintFlowQueryImpl(); - newQuery1.getFrom().addAll(partialFlow.getFrom()); - - if (partialFlow.getNotThrough() != null) - newQuery1.getNotThrough().addAll(partialFlow.getNotThrough()); - - newQuery1.getTo().add(propogator); - newQuery2.getFrom().add(propogator); - - if (partialFlow.getNotThrough() != null) - newQuery2.getNotThrough().addAll(partialFlow.getNotThrough()); - - newQuery2.getTo().addAll(partialFlow.getTo()); - subFlows.add(newQuery1); - subFlows.add(newQuery2); - } - - return subFlows; - } private List>> getReachingPairs(Boomerang boomerang, TaintFlowQueryImpl flowQuery, Set queries, @@ -167,10 +186,10 @@ private List getLogicalSubFlows( if (isValidPath(boomerang, start, end)) { if (start instanceof ForwardQuery) { reachMap.add(new DifferentTypedPair>( - flowQuery, getLocationdetailsPair(flowQuery, start, end))); + flowQuery, getLocationDetailsPair(flowQuery, start, end))); } else if (start instanceof BackwardQuery) { reachMap.add(new DifferentTypedPair>( - flowQuery, getLocationdetailsPair(flowQuery, end, start))); + flowQuery, getLocationDetailsPair(flowQuery, end, start))); } } } @@ -178,7 +197,7 @@ private List getLogicalSubFlows( return reachMap; } - private SameTypedPair getLocationdetailsPair(TaintFlowQueryImpl flowQuery, + private SameTypedPair getLocationDetailsPair(TaintFlowQueryImpl flowQuery, Query start, Query end){ LocationDetails startDetails = new LocationDetails(); @@ -210,68 +229,12 @@ private SameTypedPair getLocationdetailsPair(TaintFlowQueryImpl return new SameTypedPair(startDetails, endDetails); } - private SeedFactory getSeedFactory(TaintFlowQuery partialFlow) { - Set sourceMethods = new HashSet(); - Set sinkMethods = new HashSet(); - - return new SeedFactory() { - @Override - protected Collection generate(SootMethod method, Stmt u) { - Set out = Sets.newHashSet(); - - Collection sourceVariables = generateSourceVariables(partialFlow, method, u); - sourceVariables.forEach(v -> - out.add(new ForwardQuery(new Statement(u, method), new Val(v, method))) ); - - Collection sinkVariables = generatedSinkVariables(partialFlow, method, u); - sinkVariables.forEach(v -> - out.add(new BackwardQuery(new Statement(u, method), new Val(v, method)))); - - // Find source method - for (Method flowMethod : partialFlow.getFrom()) { - if (method.toString().equals("<" + flowMethod.getSignature() + ">")) { - sourceMethods.add(method); - } - } - - // Find target method - for (Method flowMethod : partialFlow.getTo()) { - if (method.toString().equals("<" + flowMethod.getSignature() + ">")) { - sinkMethods.add(method); - } - } - return out; - } - - @Override - public ObservableICFG icfg() { return SingleFlowAnalysis.this.icfg; } - }; - - // Note currently this is broken. See Ticket #10 on github. - // https://github.com/secure-software-engineering/secucheck/issues/10 - -// if (!sourceMethods.isEmpty()) { -// taintReporter.markMethod(sourceMethods.iterator().next(), MarkerType.SOURCE_METHOD); -// } -// -// if (!sinkMethods.isEmpty()) { -// taintReporter.markMethod(sinkMethods.iterator().next(), MarkerType.SINK_METHOD); -// } - + private SeedFactory getSeedFactory(TaintFlowQuery taintFlow) { + return new SingleFlowSeedFactory(taintFlow, this.icfg); } private Boomerang getBoomerang(SeedFactory seedFactory) { - return new Boomerang(new TaintAnalysisOptions()) { - @Override - public ObservableICFG icfg() { - return SingleFlowAnalysis.this.icfg; - } - - @Override - public SeedFactory getSeedFactory() { - return seedFactory; - } - }; + return new SingleFlowBoomerang(seedFactory, this.icfg, new TaintAnalysisOptions()); } private List getSanitizers(TaintFlowQuery partFlow) { @@ -314,111 +277,47 @@ private Map setEmptySootBodies(List methods){ return oldBodies; } - protected Collection generateSourceVariables(TaintFlowQuery partialFlow, - SootMethod method, Stmt actualStatement) { + private boolean isPropogatorless(TaintFlowQueryImpl singleFlow) { + return singleFlow.getThrough() == null || singleFlow.getThrough().size() == 0; + } + + private boolean isSourceAndSinkMatching(SameTypedPair sourcePair, + SameTypedPair sinkPair) { - for (Object object : partialFlow.getFrom()) { - Method sourceMethod = (Method) object; - String sourceSootSignature = "<" + sourceMethod.getSignature() + ">"; - Collection out = Sets.newHashSet(); - - if (method.getSignature().equals(sourceSootSignature) && - actualStatement instanceof IdentityStmt) { - - IdentityStmt identity = (IdentityStmt) actualStatement; - Value right = identity.getRightOp(); - if (right instanceof ParameterRef) { - ParameterRef parameterRef = (ParameterRef) right; - for (OutputParameter output : sourceMethod.getOutputParameters()) { - int parameterIndex = output.getNumber(); - if (parameterRef.getIndex() == parameterIndex - && method.getParameterCount() >= parameterIndex) { - out.add(identity.getLeftOp()); - } - } - } - return out; - - } else if (actualStatement.containsInvokeExpr() - && actualStatement.toString().contains(sourceSootSignature)) { - - // taint the return value - - if (sourceMethod.getReturnValue() != null && actualStatement instanceof AssignStmt) { - out.add(((AssignStmt) actualStatement).getLeftOp()); - } - - for (OutputParameter output : sourceMethod.getOutputParameters()) { - int parameterIndex = output.getNumber(); - if (actualStatement.getInvokeExpr().getArgCount() >= parameterIndex) { - out.add(actualStatement.getInvokeExpr().getArg(parameterIndex)); - } - } - - // taint this object - if (sourceMethod.isOutputThis() && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { - InstanceInvokeExpr instanceInvoke = (InstanceInvokeExpr) actualStatement.getInvokeExpr(); - out.add(instanceInvoke.getBase()); - } - - // // taint this object - // if (this.flow.getSource().getSingleSource().getTvOut() != null - // && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { - // InstanceInvokeExpr instanceInvokeExpr = (InstanceInvokeExpr) - // actualStatement.getInvokeExpr(); - // out.add(instanceInvokeExpr.getBase()); - // } - return out; - } - - } + if (!sourcePair.getSecond().getUsageClassName().equals( + sinkPair.getFirst().getUsageClassName())) + return false; + + if (!sourcePair.getSecond().getUsageMethodSignature().equals( + sinkPair.getFirst().getUsageMethodSignature())) + return false; + + if (!sourcePair.getSecond().getSourceClassName().equals( + sinkPair.getFirst().getSourceClassName())) + return false; + + if (!sourcePair.getSecond().getMethodSignature().equals( + sinkPair.getFirst().getMethodSignature())) + return false; + + if (sourcePair.getSecond().getUsageLineNumber() != + sinkPair.getFirst().getUsageLineNumber()) + return false; + + if (sourcePair.getSecond().getUsageColumnNumber() != + sinkPair.getFirst().getUsageColumnNumber()) + return false; + + return true; + } - -// if (this.flow.getSource().getValueSource() != null) // a single value source -// { -// // TODO:handle this -// } - return Collections.emptySet(); + private SameTypedPair stitchSourceAndSink( + SameTypedPair sourcePair, SameTypedPair sinkPair) { + SameTypedPair stichedPair = + new SameTypedPair<>(sourcePair.getFirst(), sinkPair.getSecond()); + return stichedPair; } - - protected Collection generatedSinkVariables(TaintFlowQuery partialFlow, - SootMethod method, Stmt actualStatement) { - for (Object object : partialFlow.getTo()) { - Method sourceMethod = (Method) object; - String sourceSootSignature = "<" + sourceMethod.getSignature() + ">"; - Collection out = Sets.newHashSet(); - - if (actualStatement.containsInvokeExpr() - && actualStatement.toString().contains(sourceSootSignature)) { - // taint the return value - for (InputParameter input : sourceMethod.getInputParameters()) { - int parameterIndex = input.getNumber(); - if (actualStatement.getInvokeExpr().getArgCount() >= parameterIndex) { - out.add(actualStatement.getInvokeExpr().getArg(parameterIndex)); - } - } - - // taint this object - if (sourceMethod.isInputThis() && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { - InstanceInvokeExpr instanceInvoke = (InstanceInvokeExpr) actualStatement.getInvokeExpr(); - out.add(instanceInvoke.getBase()); - } - - // // taint this object - // if (this.flow.getSource().getSingleSource().getTvOut() != null - // && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { - // InstanceInvokeExpr instanceInvokeExpr = (InstanceInvokeExpr) - // actualStatement.getInvokeExpr(); - // out.add(instanceInvokeExpr.getBase()); - // } - return out; - } - - } - // TODO: re-check the sink structure!! - return Collections.emptySet(); - } - + private boolean isValidPath(Boomerang boomerang, Query start, Query end) { // Quick check: Is the "end" included in the Table at all? Statement s = end.asNode().stmt(); diff --git a/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowBoomerang.java b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowBoomerang.java new file mode 100644 index 0000000..f93b9ab --- /dev/null +++ b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowBoomerang.java @@ -0,0 +1,31 @@ +package de.fraunhofer.iem.secucheck.analysis.internal; + +import boomerang.Boomerang; +import boomerang.callgraph.ObservableICFG; +import boomerang.seedfactory.SeedFactory; +import soot.SootMethod; +import soot.Unit; +import wpds.impl.Weight.NoWeight; + +public class SingleFlowBoomerang extends Boomerang { + + private final SeedFactory seedFactory; + private final ObservableICFG icfg; + + public SingleFlowBoomerang(SeedFactory seedFactory, + ObservableICFG icfg, TaintAnalysisOptions options){ + super(options); + this.seedFactory = seedFactory; + this.icfg = icfg; + } + + @Override + public ObservableICFG icfg() { + return this.icfg; + } + + @Override + public SeedFactory getSeedFactory() { + return this.seedFactory; + } +} diff --git a/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowSeedFactory.java b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowSeedFactory.java new file mode 100644 index 0000000..bf4de8d --- /dev/null +++ b/de.fraunhofer.iem.secucheck.analysis/src/main/java/de/fraunhofer/iem/secucheck/analysis/internal/SingleFlowSeedFactory.java @@ -0,0 +1,174 @@ +package de.fraunhofer.iem.secucheck.analysis.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.Sets; + +import boomerang.BackwardQuery; +import boomerang.ForwardQuery; +import boomerang.Query; +import boomerang.callgraph.ObservableICFG; +import boomerang.jimple.Statement; +import boomerang.jimple.Val; +import boomerang.seedfactory.SeedFactory; +import de.fraunhofer.iem.secucheck.analysis.query.InputParameter; +import de.fraunhofer.iem.secucheck.analysis.query.Method; +import de.fraunhofer.iem.secucheck.analysis.query.OutputParameter; +import de.fraunhofer.iem.secucheck.analysis.query.TaintFlowQuery; +import soot.SootMethod; +import soot.Unit; +import soot.Value; +import soot.jimple.AssignStmt; +import soot.jimple.IdentityStmt; +import soot.jimple.InstanceInvokeExpr; +import soot.jimple.ParameterRef; +import soot.jimple.Stmt; +import wpds.impl.Weight.NoWeight; + +public class SingleFlowSeedFactory extends SeedFactory{ + + private final TaintFlowQuery taintFlow; + private final ObservableICFG icfg; + + private final Set sourceMethods = new HashSet(); + private final Set sinkMethods = new HashSet(); + + public SingleFlowSeedFactory(TaintFlowQuery taintFlow, ObservableICFG icfg) { + this.taintFlow = taintFlow; + this.icfg = icfg; + } + + @Override + protected Collection generate(SootMethod method, Stmt u) { + Set out = Sets.newHashSet(); + + Collection sourceVariables = generateSourceVariables(this.taintFlow, method, u); + sourceVariables.forEach(v -> + out.add(new ForwardQuery(new Statement(u, method), new Val(v, method))) ); + + Collection sinkVariables = generatedSinkVariables(this.taintFlow, method, u); + sinkVariables.forEach(v -> + out.add(new BackwardQuery(new Statement(u, method), new Val(v, method)))); + + // Find source method + for (Method flowMethod : this.taintFlow.getFrom()) { + if (method.toString().equals("<" + flowMethod.getSignature() + ">")) { + sourceMethods.add(method); + } + } + + // Find target method + for (Method flowMethod : this.taintFlow.getTo()) { + if (method.toString().equals("<" + flowMethod.getSignature() + ">")) { + sinkMethods.add(method); + } + } + return out; + } + + @Override + public ObservableICFG icfg() { return this.icfg; } + + private Collection generateSourceVariables(TaintFlowQuery partialFlow, + SootMethod method, Stmt actualStatement) { + + for (Object object : partialFlow.getFrom()) { + Method sourceMethod = (Method) object; + String sourceSootSignature = "<" + sourceMethod.getSignature() + ">"; + Collection out = Sets.newHashSet(); + + if (method.getSignature().equals(sourceSootSignature) && + actualStatement instanceof IdentityStmt) { + + IdentityStmt identity = (IdentityStmt) actualStatement; + Value right = identity.getRightOp(); + if (right instanceof ParameterRef) { + + ParameterRef parameterRef = (ParameterRef) right; + if (sourceMethod.getOutputParameters() != null) { + for (OutputParameter output : sourceMethod.getOutputParameters()) { + int parameterIndex = output.getNumber(); + if (parameterRef.getIndex() == parameterIndex + && method.getParameterCount() >= parameterIndex) { + out.add(identity.getLeftOp()); + } + } + } + + } + return out; + + } else if (actualStatement.containsInvokeExpr() + && actualStatement.toString().contains(sourceSootSignature)) { + + // taint the return value + if (sourceMethod.getReturnValue() != null && actualStatement instanceof AssignStmt) { + out.add(((AssignStmt) actualStatement).getLeftOp()); + } + + if (sourceMethod.getOutputParameters() != null) { + for (OutputParameter output : sourceMethod.getOutputParameters()) { + int parameterIndex = output.getNumber(); + if (actualStatement.getInvokeExpr().getArgCount() >= parameterIndex) { + out.add(actualStatement.getInvokeExpr().getArg(parameterIndex)); + } + } + } + + // taint this object + if (sourceMethod.isOutputThis() && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { + InstanceInvokeExpr instanceInvoke = (InstanceInvokeExpr) actualStatement.getInvokeExpr(); + out.add(instanceInvoke.getBase()); + } + + return out; + } + + } + + +// if (this.flow.getSource().getValueSource() != null) // a single value source +// { +// // TODO:handle this +// } + return Collections.emptySet(); + } + + private Collection generatedSinkVariables(TaintFlowQuery partialFlow, + SootMethod method, Stmt actualStatement) { + for (Object object : partialFlow.getTo()) { + Method sourceMethod = (Method) object; + String sourceSootSignature = "<" + sourceMethod.getSignature() + ">"; + Collection out = Sets.newHashSet(); + + if (actualStatement.containsInvokeExpr() + && actualStatement.toString().contains(sourceSootSignature)) { + + // taint the return value + if (sourceMethod.getInputParameters() != null) { + for (InputParameter input : sourceMethod.getInputParameters()) { + int parameterIndex = input.getNumber(); + if (actualStatement.getInvokeExpr().getArgCount() >= parameterIndex) { + out.add(actualStatement.getInvokeExpr().getArg(parameterIndex)); + } + } + } + + // taint this object + if (sourceMethod.isInputThis() && actualStatement.getInvokeExpr() instanceof InstanceInvokeExpr) { + InstanceInvokeExpr instanceInvoke = (InstanceInvokeExpr) actualStatement.getInvokeExpr(); + out.add(instanceInvoke.getBase()); + } + + return out; + } + + } + // TODO: re-check the sink structure!! + return Collections.emptySet(); + } +}