Null pointer errors when attempting to find data flow in app
ChowChowSonic opened this issue · comments
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:
- A layout.xml with a button & nothing else
- MainActivity.java:
public class MainActivity extends AppCompatActivity {
String sample = "test";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View v = findViewById(R.id.button1);
this.setup(v);
}
public void setup(View v){
SampleClickListener l = new SampleClickListener(sample);
v.setOnClickListener(l);
l.write(sample);
}
}
- SampleClickListener.java
public class SampleClickListener implements View.OnClickListener{
String v;
public SampleClickListener(String v){
this.v = v;
this.write(v);
}
@Override
public void onClick(View v) {
String s = "test";
this.write(s);
this.write(v);
}
public void write(View v){
this.write(v.toString());
}
public void write(String s){
try {
FileWriter f = new FileWriter("testfile");
f.write(String.valueOf(v));
f.write(s);
f.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
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;
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 entire
getMorePreciseType`` method has been moved to a different class and works differently now.
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.
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.