secure-software-engineering / FlowDroid

FlowDroid Static Data Flow Tracker
GNU Lesser General Public License v2.1
1.02k stars 292 forks source link

Null pointer errors when attempting to find data flow in app #722

Closed ChowChowSonic closed 2 months ago

ChowChowSonic commented 2 months ago

Hi all, I've been having issues trying to find a dataflow in a test APK I wrote. I've defined a few sources in code & have a bunch of sinks in a file that flowdroid reads off of. I've been running an infoflow twice each test - once before adding sources, once after - and I don't get any errors on the first run of Flowdroid, only the second. I have found a solution after looking into the code, although I'm sure there are other or better ways to fix this. Below is a summary of what I have & my solution. If there's anything else I can provide to help fix this please let me know:

Flowdroid version: 2.11.1 I am using a test apk with 3 files:

My sources and sinks file (sources are defined via the API):

%<com.example.iotestjavaapp.SampleClickListener: void write(java.lang.String)> -> _SINK_
%<com.example.iotestjavaapp.SampleClickListener: void write(android.view.View)> -> _SINK_
% uncomment above lines to fix errors
<java.io.Writer: java.io.Writer append(char)> -> _SINK_ 
<java.io.Writer: java.io.Writer append(java.lang.CharSequence)> -> _SINK_ 
<java.io.Writer: java.io.Writer append(java.lang.CharSequence, int, int)> -> _SINK_ 
<java.io.Writer: void close()> -> _SINK_ 
<java.io.Writer: void flush()> -> _SINK_ 
<java.io.Writer: void write(char[])> -> _SINK_ 
<java.io.Writer: void write(char[], int, int)> -> _SINK_ 
<java.io.Writer: void write(int)> -> _SINK_ 
<java.io.Writer: void write(java.lang.String)> -> _SINK_ 
<java.io.Writer: void write(java.lang.String, int, int)> -> _SINK_ 

The Flowdroid setup i'm using (Irrelevant code has been left out):

SetupApplication app = new SetupApplication(jar, "src/main/resources/" + apkstr);
InfoflowAndroidConfiguration conf = app.getConfig();
app.setTaintWrapper(new SummaryTaintWrapper(new LazySummaryProvider("summariesManual")));
conf.getAnalysisFileConfig().setSourceSinkFile("src\\main\\resources\\dummySrcSnk.txt");
conf.getPathConfiguration().setPathReconstructionMode(PathReconstructionMode.Precise);
conf.setMergeDexFiles(true);
InfoflowResults res = app.runInfoflow();
conf.setSootIntegrationMode(SootIntegrationMode.UseExistingCallgraph);
SrcSinkHolder holder = new SrcSinkHolder(app); //loads app's sources and sinks into internal arrays
System.out.println("callgraph generated"); 
SootMethod f = getFunction("<com.example.iotestjavaapp.MainActivity: void setup(android.view.View)>");

holder.addLineSource((JimpleBody)f.getActiveBody(), "r2 = new com.example.iotestjavaapp.SampleClickListener", "r2");
res = app.runInfoflow(holder);          

Errors I'm getting: [FlowDroid] ERROR heros.solver.CountingThreadPoolExecutor - Worker thread execution failed: Cannot invoke "Object.hashCode()" because "key" is null java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964) at soot.jimple.infoflow.collect.ConcurrentHashSet.contains(ConcurrentHashSet.java:48) at soot.jimple.infoflow.methodSummary.data.provider.LazySummaryProvider.getClassFlows(LazySummaryProvider.java:146) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getMorePreciseType(SummaryTaintWrapper.java:1829) at soot.jimple.infoflow.typing.TypeUtils.getMorePreciseType(TypeUtils.java:195) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.addSinkTaint(SummaryTaintWrapper.java:1383) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlow(SummaryTaintWrapper.java:1059) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlowsIterative(SummaryTaintWrapper.java:666) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.computeTaintsForMethod(SummaryTaintWrapper.java:607) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getTaintsForMethod(SummaryTaintWrapper.java:482) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.computeWrapperTaints(WrapperPropagationRule.java:94) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.propagateCallToReturnFlow(WrapperPropagationRule.java:148) at soot.jimple.infoflow.problems.rules.PropagationRuleManager.applyCallToReturnFlowFunction(PropagationRuleManager.java:167) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargetsInternal(InfoflowProblem.java:771) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargets(InfoflowProblem.java:748) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:98) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:1) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.processCall(IFDSSolver.java:356) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.access$0(IFDSSolver.java:298) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver$PathEdgeProcessingTask.runInternal(IFDSSolver.java:772) at soot.jimple.infoflow.solver.fastSolver.LocalWorklistTask.run(LocalWorklistTask.java:27) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) [FlowDroid] ERROR heros.solver.CountingThreadPoolExecutor - Worker thread execution failed: Cannot invoke "Object.hashCode()" because "key" is null java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964) at soot.jimple.infoflow.collect.ConcurrentHashSet.contains(ConcurrentHashSet.java:48) at soot.jimple.infoflow.methodSummary.data.provider.LazySummaryProvider.getClassFlows(LazySummaryProvider.java:146) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getMorePreciseType(SummaryTaintWrapper.java:1829) at soot.jimple.infoflow.typing.TypeUtils.getMorePreciseType(TypeUtils.java:195) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.addSinkTaint(SummaryTaintWrapper.java:1383) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlow(SummaryTaintWrapper.java:1059) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlowsIterative(SummaryTaintWrapper.java:666) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.computeTaintsForMethod(SummaryTaintWrapper.java:607) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getTaintsForMethod(SummaryTaintWrapper.java:482) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.computeWrapperTaints(WrapperPropagationRule.java:94) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.propagateCallToReturnFlow(WrapperPropagationRule.java:148) at soot.jimple.infoflow.problems.rules.PropagationRuleManager.applyCallToReturnFlowFunction(PropagationRuleManager.java:167) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargetsInternal(InfoflowProblem.java:771) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargets(InfoflowProblem.java:748) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:98) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:1) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.processCall(IFDSSolver.java:356) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.access$0(IFDSSolver.java:298) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver$PathEdgeProcessingTask.runInternal(IFDSSolver.java:772) at soot.jimple.infoflow.solver.fastSolver.LocalWorklistTask.run(LocalWorklistTask.java:27) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) Exception in thread "FlowDroid" java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964) at soot.jimple.infoflow.collect.ConcurrentHashSet.contains(ConcurrentHashSet.java:48) at soot.jimple.infoflow.methodSummary.data.provider.LazySummaryProvider.getClassFlows(LazySummaryProvider.java:146) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getMorePreciseType(SummaryTaintWrapper.java:1829) at soot.jimple.infoflow.typing.TypeUtils.getMorePreciseType(TypeUtils.java:195) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.addSinkTaint(SummaryTaintWrapper.java:1383) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlow(SummaryTaintWrapper.java:1059) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlowsIterative(SummaryTaintWrapper.java:666) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.computeTaintsForMethod(SummaryTaintWrapper.java:607) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getTaintsForMethod(SummaryTaintWrapper.java:482) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.computeWrapperTaints(WrapperPropagationRule.java:94) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.propagateCallToReturnFlow(WrapperPropagationRule.java:148) at soot.jimple.infoflow.problems.rules.PropagationRuleManager.applyCallToReturnFlowFunction(PropagationRuleManager.java:167) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargetsInternal(InfoflowProblem.java:771) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargets(InfoflowProblem.java:748) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:98) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:1) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.processCall(IFDSSolver.java:356) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.access$0(IFDSSolver.java:298) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver$PathEdgeProcessingTask.runInternal(IFDSSolver.java:772) at soot.jimple.infoflow.solver.fastSolver.LocalWorklistTask.run(LocalWorklistTask.java:27) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) [main] INFO soot.jimple.infoflow.memory.MemoryWarningSystem - Shutting down the memory warning system... Exception in thread "FlowDroid" java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964) at soot.jimple.infoflow.collect.ConcurrentHashSet.contains(ConcurrentHashSet.java:48) at soot.jimple.infoflow.methodSummary.data.provider.LazySummaryProvider.getClassFlows(LazySummaryProvider.java:146) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getMorePreciseType(SummaryTaintWrapper.java:1829) at soot.jimple.infoflow.typing.TypeUtils.getMorePreciseType(TypeUtils.java:195) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.addSinkTaint(SummaryTaintWrapper.java:1383) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlow(SummaryTaintWrapper.java:1059) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlowsIterative(SummaryTaintWrapper.java:666) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.computeTaintsForMethod(SummaryTaintWrapper.java:607) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getTaintsForMethod(SummaryTaintWrapper.java:482) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.computeWrapperTaints(WrapperPropagationRule.java:94) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.propagateCallToReturnFlow(WrapperPropagationRule.java:148) at soot.jimple.infoflow.problems.rules.PropagationRuleManager.applyCallToReturnFlowFunction(PropagationRuleManager.java:167) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargetsInternal(InfoflowProblem.java:771) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargets(InfoflowProblem.java:748) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:98) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:1) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.processCall(IFDSSolver.java:356) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.access$0(IFDSSolver.java:298) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver$PathEdgeProcessingTask.runInternal(IFDSSolver.java:772) at soot.jimple.infoflow.solver.fastSolver.LocalWorklistTask.run(LocalWorklistTask.java:27) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) [main] ERROR soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Exception during data flow analysis java.lang.RuntimeException: There were exceptions during IFDS analysis. Exiting. at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.runExecutorAndAwaitCompletion(IFDSSolver.java:264) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.awaitCompletionComputeValuesAndShutdown(IFDSSolver.java:231) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.solve(IFDSSolver.java:203) at soot.jimple.infoflow.AbstractInfoflow.runTaintAnalysis(AbstractInfoflow.java:820) at soot.jimple.infoflow.AbstractInfoflow.runAnalysis(AbstractInfoflow.java:608) at soot.jimple.infoflow.AbstractInfoflow.runAnalysis(AbstractInfoflow.java:544) at soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow.runAnalysis(SetupApplication.java:1305) at soot.jimple.infoflow.android.SetupApplication.processEntryPoint(SetupApplication.java:1594) at soot.jimple.infoflow.android.SetupApplication.runInfoflow(SetupApplication.java:1529) at research.app.main(app.java:56) Caused by: java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964) at soot.jimple.infoflow.collect.ConcurrentHashSet.contains(ConcurrentHashSet.java:48) at soot.jimple.infoflow.methodSummary.data.provider.LazySummaryProvider.getClassFlows(LazySummaryProvider.java:146) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getMorePreciseType(SummaryTaintWrapper.java:1829) at soot.jimple.infoflow.typing.TypeUtils.getMorePreciseType(TypeUtils.java:195) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.addSinkTaint(SummaryTaintWrapper.java:1383) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlow(SummaryTaintWrapper.java:1059) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.applyFlowsIterative(SummaryTaintWrapper.java:666) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.computeTaintsForMethod(SummaryTaintWrapper.java:607) at soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper.getTaintsForMethod(SummaryTaintWrapper.java:482) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.computeWrapperTaints(WrapperPropagationRule.java:94) at soot.jimple.infoflow.problems.rules.forward.WrapperPropagationRule.propagateCallToReturnFlow(WrapperPropagationRule.java:148) at soot.jimple.infoflow.problems.rules.PropagationRuleManager.applyCallToReturnFlowFunction(PropagationRuleManager.java:167) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargetsInternal(InfoflowProblem.java:771) at soot.jimple.infoflow.problems.InfoflowProblem$1$4.computeTargets(InfoflowProblem.java:748) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:98) at soot.jimple.infoflow.solver.fastSolver.InfoflowSolver.computeCallToReturnFlowFunction(InfoflowSolver.java:1) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.processCall(IFDSSolver.java:356) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver.access$0(IFDSSolver.java:298) at soot.jimple.infoflow.solver.fastSolver.IFDSSolver$PathEdgeProcessingTask.runInternal(IFDSSolver.java:772) at soot.jimple.infoflow.solver.fastSolver.LocalWorklistTask.run(LocalWorklistTask.java:27) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583)

A solution that worked for me:

/**
 * Class representing the method summaries for a single class
 * 
 * @author Steven Arzt
 *
 */
public class ClassMethodSummaries {

    private final String className;
    private final MethodSummaries methodSummaries;
    private final Set<String> interfaces = new HashSet<>();
    private String superClass; <-- null
    private Boolean isInterface = null;

Changed to:

/**
 * Class representing the method summaries for a single class
 * 
 * @author Steven Arzt
 *
 */
public class ClassMethodSummaries {

    private final String className;
    private final MethodSummaries methodSummaries;
    private final Set<String> interfaces = new HashSet<>();
    private String superClass = ""; <-- changed
    private Boolean isInterface = null;
StevenArzt commented 2 months ago

Can you reproduce the issue with the latest FlowDroid version from the "develop" branch? I would say that there is a missing nullness check in the SummaryTaintWrapper'', but the code has changed significantly. The entiregetMorePreciseType`` method has been moved to a different class and works differently now.

ChowChowSonic commented 2 months ago

Hi @StevenArzt, Sorry for the late reply, this week has been hectic for me. I have updated to the most recent version of Flowdroid from Develop and it appears that the error is gone. However, I'll let you know if anything similar pops up. Thank you for your work on Flowdroid & your help with this.

StevenArzt commented 2 months ago

We have just released a new version to Maven central. If you don't want to use development branches, you can also update to the latest stable version.