Skip to content

Commit 03007f8

Browse files
authored
Merge pull request #385 from MobileSE/develop
Improve FlowDroid to support Field Sources(develop branch)
2 parents b1c46a9 + d0a9183 commit 03007f8

File tree

5 files changed

+226
-38
lines changed

5 files changed

+226
-38
lines changed

soot-infoflow-android/src/soot/jimple/infoflow/android/SetupApplication.java

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,12 @@
1010
******************************************************************************/
1111
package soot.jimple.infoflow.android;
1212

13-
import java.io.File;
14-
import java.io.IOException;
15-
import java.util.ArrayList;
16-
import java.util.Collection;
17-
import java.util.Collections;
18-
import java.util.HashMap;
19-
import java.util.HashSet;
20-
import java.util.Iterator;
21-
import java.util.List;
22-
import java.util.Map;
23-
import java.util.Set;
24-
25-
import javax.xml.stream.XMLStreamException;
26-
13+
import heros.solver.Pair;
2714
import org.slf4j.Logger;
2815
import org.slf4j.LoggerFactory;
2916
import org.xml.sax.SAXException;
3017
import org.xmlpull.v1.XmlPullParserException;
31-
32-
import heros.solver.Pair;
33-
import soot.G;
34-
import soot.Main;
35-
import soot.PackManager;
36-
import soot.Scene;
37-
import soot.SootClass;
38-
import soot.SootField;
39-
import soot.SootMethod;
40-
import soot.Unit;
18+
import soot.*;
4119
import soot.jimple.Stmt;
4220
import soot.jimple.infoflow.AbstractInfoflow;
4321
import soot.jimple.infoflow.IInfoflow;
@@ -108,6 +86,11 @@
10886
import soot.util.HashMultiMap;
10987
import soot.util.MultiMap;
11088

89+
import javax.xml.stream.XMLStreamException;
90+
import java.io.File;
91+
import java.io.IOException;
92+
import java.util.*;
93+
11194
public class SetupApplication implements ITaintWrapperDataFlowAnalysis {
11295

11396
private final Logger logger = LoggerFactory.getLogger(getClass());

soot-infoflow-android/src/soot/jimple/infoflow/android/data/parsers/PermissionMethodParser.java

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@
2929
import org.slf4j.LoggerFactory;
3030

3131
import soot.jimple.infoflow.android.data.AndroidMethod;
32-
import soot.jimple.infoflow.sourcesSinks.definitions.ISourceSinkDefinition;
33-
import soot.jimple.infoflow.sourcesSinks.definitions.ISourceSinkDefinitionProvider;
34-
import soot.jimple.infoflow.sourcesSinks.definitions.MethodSourceSinkDefinition;
35-
import soot.jimple.infoflow.sourcesSinks.definitions.SourceSinkType;
32+
import soot.jimple.infoflow.data.SootFieldAndClass;
33+
import soot.jimple.infoflow.sourcesSinks.definitions.*;
3634

3735
/**
3836
* Parser for the permissions to method map of Adrienne Porter Felt.
@@ -44,6 +42,7 @@ public class PermissionMethodParser implements ISourceSinkDefinitionProvider {
4442
private final Logger logger = LoggerFactory.getLogger(getClass());
4543

4644
private Map<String, AndroidMethod> methods = null;
45+
private Map<String, SootFieldAndClass> fields = null;
4746
private Set<ISourceSinkDefinition> sourceList = null;
4847
private Set<ISourceSinkDefinition> sinkList = null;
4948
private Set<ISourceSinkDefinition> neitherList = null;
@@ -56,6 +55,8 @@ public class PermissionMethodParser implements ISourceSinkDefinitionProvider {
5655
// "^<(.+):\\s(.+)\\s?(.+)\\s*\\((.*)\\)>\\s+(.*?)(\\s+->\\s+(.*))?+$";
5756
private final String regexNoRet = "^<(.+):\\s*(.+)\\s*\\((.*)\\)>\\s*(.*?)?(\\s+->\\s+(.*))?$";
5857

58+
private final String fieldRegex = "^<(.+):\\s*(.+)\\s+([a-zA-Z_$][a-zA-Z_$0-9]*)\\s*>\\s*(.*?)(\\s+->\\s+(.*))?$";
59+
5960
public static PermissionMethodParser fromFile(String fileName) throws IOException {
6061
PermissionMethodParser pmp = new PermissionMethodParser();
6162
pmp.readFile(fileName);
@@ -119,30 +120,39 @@ public Set<ISourceSinkDefinition> getSinks() {
119120
}
120121

121122
private void parse() {
123+
fields = new HashMap<>(INITIAL_SET_SIZE);
122124
methods = new HashMap<>(INITIAL_SET_SIZE);
123125
sourceList = new HashSet<>(INITIAL_SET_SIZE);
124126
sinkList = new HashSet<>(INITIAL_SET_SIZE);
125127
neitherList = new HashSet<>(INITIAL_SET_SIZE);
126128

127129
Pattern p = Pattern.compile(regex);
128130
Pattern pNoRet = Pattern.compile(regexNoRet);
131+
Pattern fieldPattern = Pattern.compile(fieldRegex);
129132

130133
for (String line : this.data) {
131134
if (line.isEmpty() || line.startsWith("%"))
132135
continue;
133-
Matcher m = p.matcher(line);
134-
if (m.find()) {
135-
createMethod(m);
136-
} else {
137-
Matcher mNoRet = pNoRet.matcher(line);
138-
if (mNoRet.find()) {
139-
createMethod(mNoRet);
140-
} else
141-
logger.warn(String.format("Line does not match: %s", line));
136+
//match field regex
137+
Matcher fieldMatch = fieldPattern.matcher(line);
138+
if (fieldMatch.find()) {
139+
createField(fieldMatch);
140+
}else{
141+
//match method regex
142+
Matcher m = p.matcher(line);
143+
if (m.find()) {
144+
createMethod(m);
145+
} else {
146+
Matcher mNoRet = pNoRet.matcher(line);
147+
if (mNoRet.find()) {
148+
createMethod(mNoRet);
149+
} else
150+
logger.warn(String.format("Line does not match: %s", line));
151+
}
142152
}
143153
}
144154

145-
// Create the source/sink definitions
155+
// Create the source/sink definitions[for method]
146156
for (AndroidMethod am : methods.values()) {
147157
MethodSourceSinkDefinition singleMethod = new MethodSourceSinkDefinition(am);
148158

@@ -153,6 +163,18 @@ private void parse() {
153163
if (am.getSourceSinkType() == SourceSinkType.Neither)
154164
neitherList.add(singleMethod);
155165
}
166+
167+
// Create the source/sink definitions[for field]
168+
for (SootFieldAndClass sootField : fields.values()) {
169+
FieldSourceSinkDefinition fieldDefinition = new FieldSourceSinkDefinition(sootField.getSignature());
170+
171+
if (sootField.getSourceSinkType().isSource())
172+
sourceList.add(fieldDefinition);
173+
if (sootField.getSourceSinkType().isSink())
174+
sinkList.add(fieldDefinition);
175+
if (sootField.getSourceSinkType() == SourceSinkType.Neither)
176+
neitherList.add(fieldDefinition);
177+
}
156178
}
157179

158180
private AndroidMethod createMethod(Matcher m) {
@@ -254,4 +276,41 @@ public Set<ISourceSinkDefinition> getAllMethods() {
254276
sourcesSinks.addAll(neitherList);
255277
return sourcesSinks;
256278
}
279+
280+
private SootFieldAndClass createField(Matcher m) {
281+
SootFieldAndClass sootField = parseField(m);
282+
SootFieldAndClass oldField = fields.get(sootField.getSignature());
283+
if (oldField != null) {
284+
oldField.setSourceSinkType(oldField.getSourceSinkType().addType(sootField.getSourceSinkType()));
285+
return oldField;
286+
} else {
287+
fields.put(sootField.getSignature(), sootField);
288+
return sootField;
289+
}
290+
}
291+
292+
private SootFieldAndClass parseField(Matcher m) {
293+
assert (m.group(1) != null && m.group(2) != null && m.group(3) != null && m.group(4) != null);
294+
SootFieldAndClass sootFieldAndClass;
295+
int groupIdx = 1;
296+
297+
// class name
298+
String className = m.group(groupIdx++).trim();
299+
300+
// field type
301+
String fieldType = m.group(groupIdx++).trim();
302+
303+
// field name
304+
String fieldName = m.group(groupIdx++).trim();
305+
306+
// SourceSinkType
307+
String sourceSinkTypeString = m.group(groupIdx).replace("->", "").replace("_","").trim();
308+
SourceSinkType sourceSinkType = SourceSinkType.fromString(sourceSinkTypeString);
309+
310+
// create Field signature
311+
sootFieldAndClass = new SootFieldAndClass(fieldName, className, fieldType, sourceSinkType);
312+
313+
return sootFieldAndClass;
314+
}
315+
257316
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package soot.jimple.infoflow.android.test.droidBench;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
import org.xmlpull.v1.XmlPullParserException;
6+
import soot.jimple.infoflow.results.InfoflowResults;
7+
8+
import java.io.IOException;
9+
10+
public class FieldSourceTest extends JUnitTests {
11+
12+
@Test
13+
public void runTestFlowSensitivity1() throws IOException, XmlPullParserException {
14+
InfoflowResults res = analyzeAPKFile("FieldSource/FieldSourceTest.apk");
15+
Assert.assertNotNull(res);
16+
}
17+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package soot.jimple.infoflow.data;
2+
3+
import soot.jimple.infoflow.sourcesSinks.definitions.SourceSinkType;
4+
5+
public class SootFieldAndClass {
6+
7+
private final String fieldName;
8+
private final String className;
9+
private final String fieldType;
10+
private Boolean isStatic;
11+
private SourceSinkType sourceSinkType = SourceSinkType.Undefined;
12+
13+
private int hashCode = 0;
14+
private String signature = null;
15+
16+
public SootFieldAndClass(String fieldName, String className, String fieldType, SourceSinkType sourceSinkType) {
17+
this.fieldName = fieldName;
18+
this.className = className;
19+
this.fieldType = fieldType;
20+
this.sourceSinkType = sourceSinkType;
21+
}
22+
23+
public String getFieldName() {
24+
return fieldName;
25+
}
26+
27+
public String getClassName() {
28+
return className;
29+
}
30+
31+
public String getFieldType() {
32+
return fieldType;
33+
}
34+
35+
public SourceSinkType getSourceSinkType() {
36+
return sourceSinkType;
37+
}
38+
39+
public void setSourceSinkType(SourceSinkType sourceSinkType) {
40+
this.sourceSinkType = sourceSinkType;
41+
}
42+
43+
public Boolean getStatic() {
44+
return isStatic;
45+
}
46+
47+
public void setStatic(Boolean aStatic) {
48+
isStatic = aStatic;
49+
}
50+
51+
public String getSignature() {
52+
if (signature != null)
53+
return signature;
54+
55+
StringBuilder sb = new StringBuilder(10 + this.className.length() + this.fieldType.length()
56+
+ this.fieldName.length());
57+
sb.append("<");
58+
sb.append(this.className);
59+
sb.append(": ");
60+
if (!this.fieldType.isEmpty()) {
61+
sb.append(this.fieldType);
62+
sb.append(" ");
63+
}
64+
sb.append(this.fieldName);
65+
sb.append(">");
66+
this.signature = sb.toString();
67+
68+
return this.signature;
69+
}
70+
71+
public void setSignature(String signature) {
72+
this.signature = signature;
73+
}
74+
75+
public int getHashCode() {
76+
return hashCode;
77+
}
78+
79+
@Override
80+
public int hashCode() {
81+
if (this.hashCode == 0)
82+
this.hashCode = this.fieldName.hashCode() + this.className.hashCode() * 5;
83+
return this.hashCode;
84+
}
85+
86+
@Override
87+
public boolean equals(Object another) {
88+
if (!(another instanceof SootFieldAndClass))
89+
return false;
90+
SootFieldAndClass otherMethod = (SootFieldAndClass) another;
91+
92+
if (!this.fieldName.equals(otherMethod.fieldName))
93+
return false;
94+
if (!this.className.equals(otherMethod.className))
95+
return false;
96+
if (!this.fieldType.equals(otherMethod.fieldType))
97+
return false;
98+
return true;
99+
}
100+
101+
@Override
102+
public String toString() {
103+
StringBuilder sb = new StringBuilder();
104+
sb.append("<");
105+
sb.append(className);
106+
sb.append(": ");
107+
sb.append(fieldType);
108+
sb.append(" ");
109+
sb.append(fieldName);
110+
sb.append(">");
111+
return sb.toString();
112+
}
113+
114+
}

soot-infoflow/src/soot/jimple/infoflow/sourcesSinks/definitions/SourceSinkType.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,19 @@ public SourceSinkType addType(SourceSinkType toAdd) {
107107
return this;
108108
}
109109

110+
public static SourceSinkType fromString(String sourceSinkTypeString) {
111+
switch (sourceSinkTypeString) {
112+
case "NONE":
113+
return Neither;
114+
case "SOURCE":
115+
return Source;
116+
case "SINK":
117+
return Sink;
118+
case "BOTH":
119+
return Both;
120+
}
121+
//return Undefined;
122+
throw new RuntimeException("[SourceSinkType.sourceSinkTypeString]error in target definition: " + sourceSinkTypeString);
123+
}
124+
110125
}

0 commit comments

Comments
 (0)