|
1 | 1 | package soot.jimple.infoflow.integration.test.junit; |
2 | 2 |
|
3 | 3 | import org.junit.Assert; |
| 4 | +import org.junit.Assume; |
4 | 5 | import org.junit.Test; |
5 | 6 | import org.xmlpull.v1.XmlPullParserException; |
| 7 | +import soot.SootMethod; |
6 | 8 | import soot.jimple.infoflow.InfoflowConfiguration; |
7 | 9 | import soot.jimple.infoflow.android.SetupApplication; |
| 10 | +import soot.jimple.infoflow.android.data.parsers.PermissionMethodParser; |
8 | 11 | import soot.jimple.infoflow.methodSummary.data.provider.EagerSummaryProvider; |
9 | 12 | import soot.jimple.infoflow.methodSummary.taintWrappers.SummaryTaintWrapper; |
10 | 13 | import soot.jimple.infoflow.methodSummary.taintWrappers.TaintWrapperFactory; |
| 14 | +import soot.jimple.infoflow.results.DataFlowResult; |
11 | 15 | import soot.jimple.infoflow.results.InfoflowResults; |
12 | 16 | import soot.jimple.infoflow.taintWrappers.ITaintPropagationWrapper; |
| 17 | +import soot.jimple.infoflow.util.DebugFlowFunctionTaintPropagationHandler; |
13 | 18 |
|
| 19 | +import javax.swing.text.html.parser.Parser; |
14 | 20 | import javax.xml.stream.XMLStreamException; |
| 21 | +import java.io.BufferedReader; |
| 22 | +import java.io.ByteArrayInputStream; |
15 | 23 | import java.io.IOException; |
16 | 24 | import java.net.URISyntaxException; |
17 | | -import java.util.Collections; |
| 25 | +import java.util.*; |
18 | 26 |
|
19 | 27 | /** |
20 | 28 | * Tests that uncovered a bug. |
@@ -43,4 +51,41 @@ public void testFlowSensitivityWithOverwrite() throws XmlPullParserException, IO |
43 | 51 | Assert.assertEquals(2, results.size()); |
44 | 52 | Assert.assertEquals(2, results.getResultSet().size()); |
45 | 53 | } |
| 54 | + |
| 55 | + /** |
| 56 | + * Tests an app that uses the kotlin collections. |
| 57 | + * Expects four leaks: |
| 58 | + * * From getDeviceId() in onCreate() to Log.d(String, String) |
| 59 | + * in listFlow(String), mapFlow(String) and setFlow(String). |
| 60 | + * * From new File in fileFlow() to Log.d(String, String) in fileFlow(String). |
| 61 | + */ |
| 62 | + @Test |
| 63 | + public void testKotlinAppWithCollections() throws IOException { |
| 64 | + |
| 65 | + SetupApplication app = initApplication("testAPKs/KotlinCollectionApp.apk"); |
| 66 | + |
| 67 | + // Make sure we find only one flow per method |
| 68 | + app.addResultsAvailableHandler((cfg, results) -> { |
| 69 | + Set<SootMethod> seenSet = new HashSet<>(); |
| 70 | + for (DataFlowResult res : results.getResultSet()) { |
| 71 | + SootMethod sm = cfg.getMethodOf(res.getSink().getStmt()); |
| 72 | + Assert.assertFalse(seenSet.contains(sm)); |
| 73 | + seenSet.add(sm); |
| 74 | + } |
| 75 | + }); |
| 76 | + |
| 77 | + // Add the sources and sinks |
| 78 | + List<String> ssinks = new ArrayList<>(); |
| 79 | + ssinks.add("<android.telephony.TelephonyManager: java.lang.String getDeviceId()> android.permission.READ_PHONE_STATE -> _SOURCE_"); |
| 80 | + ssinks.add("<android.util.Log: int d(java.lang.String,java.lang.String)> -> _SINK_"); |
| 81 | + ssinks.add("<kotlin.io.TextStreamsKt: java.util.List readLines(java.io.Reader)> -> _SOURCE_"); |
| 82 | + |
| 83 | + // TODO: Triggers an NPE in the backward direction in Soot |
| 84 | + // because the hierarchy for a phantom class is not initialized. |
| 85 | + Assume.assumeTrue(app.getConfig().getDataFlowDirection() == InfoflowConfiguration.DataFlowDirection.Forwards); |
| 86 | + |
| 87 | + InfoflowResults results = app.runInfoflow(PermissionMethodParser.fromStringList(ssinks)); |
| 88 | + Assert.assertEquals(4, results.size()); |
| 89 | + Assert.assertEquals(4, results.getResultSet().size()); |
| 90 | + } |
46 | 91 | } |
0 commit comments