Skip to content

Commit 25ddc0c

Browse files
committed
Merge branch 'develop' of github.com:secure-software-engineering/FlowDroid into develop
2 parents 864382e + 809b78f commit 25ddc0c

11 files changed

Lines changed: 164 additions & 86 deletions

File tree

README.MD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ Steven Arzt</a> is a good place to start.
109109
## Contributing to FlowDroid
110110

111111
Contributions are always welcome. FlowDroid is an open source project that we published in the hope that it will be useful to
112-
the research community as a whole. If you have a new feature of a bug fix that you would like to see in the official code
112+
the research community as a whole. If you have a new feature or a bug fix that you would like to see in the official code
113113
repository, please open a merge request here on Github and contact us (see below) with a short description of what you have
114114
done.
115115

soot-infoflow-android/src/soot/jimple/infoflow/android/iccta/IccRedirectionCreator.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ protected SootMethod generateRedirectMethodForStartActivityForResult(SootClass o
181181
dummyMainClass.addMethod(newSM);
182182
final JimpleBody b = Jimple.v().newBody(newSM);
183183
newSM.setActiveBody(b);
184+
newSM.addTag(SimulatedCodeElementTag.TAG);
184185

185186
LocalGenerator lg = new LocalGenerator(b);
186187

@@ -228,13 +229,14 @@ protected SootMethod generateRedirectMethodForStartActivityForResult(SootClass o
228229
protected SootMethod generateRedirectMethod(SootClass wrapper) {
229230
SootMethod targetDummyMain = componentToEntryPoint.getEntryPoint(wrapper);
230231
if (targetDummyMain == null) {
231-
logger.warn(String.format("Destination component %s has no dummy main method", wrapper.getName()));
232+
logger.warn("Destination component {} has no dummy main method", wrapper.getName());
232233
return null;
233234
}
234235

235236
String newSM_name = "redirector" + num++;
236237
SootMethod newSM = Scene.v().makeSootMethod(newSM_name, Collections.<Type>singletonList(INTENT_TYPE),
237238
VoidType.v(), Modifier.STATIC | Modifier.PUBLIC);
239+
newSM.addTag(SimulatedCodeElementTag.TAG);
238240
dummyMainClass.addMethod(newSM);
239241
JimpleBody b = Jimple.v().newBody(newSM);
240242
newSM.setActiveBody(b);
@@ -260,12 +262,13 @@ protected SootMethod generateRedirectMethod(SootClass wrapper) {
260262
protected SootMethod generateRedirectMethodForStartActivity(SootClass wrapper) {
261263
SootMethod targetDummyMain = componentToEntryPoint.getEntryPoint(wrapper);
262264
if (targetDummyMain == null) {
263-
logger.warn(String.format("Destination component %s has no dummy main method", wrapper.getName()));
265+
logger.warn("Destination component {} has no dummy main method", wrapper.getName());
264266
return null;
265267
}
266268
String newSM_name = "redirector" + num++;
267269
SootMethod newSM = Scene.v().makeSootMethod(newSM_name, Collections.<Type>singletonList(INTENT_TYPE),
268270
VoidType.v(), Modifier.STATIC | Modifier.PUBLIC);
271+
newSM.addTag(SimulatedCodeElementTag.TAG);
269272
dummyMainClass.addMethod(newSM);
270273
JimpleBody b = Jimple.v().newBody(newSM);
271274
newSM.setActiveBody(b);
@@ -291,12 +294,12 @@ protected SootMethod generateRedirectMethodForStartActivity(SootClass wrapper) {
291294
protected SootMethod generateRedirectMethodForBindService(SootClass serviceConnection, SootClass destComp) {
292295
ServiceEntryPointInfo entryPointInfo = (ServiceEntryPointInfo) componentToEntryPoint.get(destComp);
293296
if (entryPointInfo == null) {
294-
logger.warn(String.format("Destination component %s has no dummy main method", destComp.getName()));
297+
logger.warn("Destination component {} has no dummy main method", destComp.getName());
295298
return null;
296299
}
297300
SootMethod targetDummyMain = entryPointInfo.getEntryPoint();
298301
if (targetDummyMain == null) {
299-
logger.warn(String.format("Destination component %s has no dummy main method", destComp.getName()));
302+
logger.warn("Destination component {} has no dummy main method", destComp.getName());
300303
return null;
301304
}
302305
String newSM_name = "redirector" + num++;
@@ -307,6 +310,7 @@ protected SootMethod generateRedirectMethodForBindService(SootClass serviceConne
307310

308311
SootMethod newSM = Scene.v().makeSootMethod(newSM_name, newSM_parameters, VoidType.v(),
309312
Modifier.STATIC | Modifier.PUBLIC);
313+
newSM.addTag(SimulatedCodeElementTag.TAG);
310314
dummyMainClass.addMethod(newSM);
311315
JimpleBody b = Jimple.v().newBody(newSM);
312316
newSM.setActiveBody(b);
@@ -342,7 +346,7 @@ protected SootMethod generateRedirectMethodForBindService(SootClass serviceConne
342346
Local iLocal1 = lg.generateLocal(RefType.v("android.content.ComponentName"));
343347
b.getUnits().add(Jimple.v().newAssignStmt(iLocal1, NullConstant.v()));
344348

345-
List<Value> args = new ArrayList<Value>();
349+
List<Value> args = new ArrayList<>();
346350
args.add(iLocal1);
347351
args.add(ibinderLocal);
348352
SootClass sc = Scene.v().getSootClass(originActivityParameterLocal.getType().toString());
@@ -363,6 +367,7 @@ protected SootMethod generateRedirectMethodForContentProvider(Stmt iccStmt, Soot
363367
String newSM_name = "redirector" + num++;
364368
SootMethod newSM = Scene.v().makeSootMethod(newSM_name, iccMethod.getParameterTypes(),
365369
iccMethod.getReturnType(), Modifier.STATIC | Modifier.PUBLIC);
370+
newSM.addTag(SimulatedCodeElementTag.TAG);
366371
dummyMainClass.addMethod(newSM);
367372
JimpleBody b = Jimple.v().newBody(newSM);
368373
newSM.setActiveBody(b);
@@ -419,7 +424,7 @@ protected void insertRedirectMethodCallAfterIccMethod(IccLink link, SootMethod r
419424

420425
// specially deal with startActivityForResult since they have two
421426
// parameters
422-
List<Value> args = new ArrayList<Value>();
427+
List<Value> args = new ArrayList<>();
423428
if (callee.getNumberedSubSignature().equals(subsigStartActivityForResult)) {
424429
InstanceInvokeExpr iiexpr = (InstanceInvokeExpr) fromStmt.getInvokeExpr();
425430
args.add(iiexpr.getBase());
@@ -451,8 +456,9 @@ protected void insertRedirectMethodCallAfterIccMethod(IccLink link, SootMethod r
451456
redirectCallU.addTag(SimulatedCodeElementTag.TAG);
452457
units.insertAfter(redirectCallU, link.getFromU());
453458
instrumentedUnits.put(body, redirectCallU);
454-
if (instrumentationCallback != null)
459+
if (instrumentationCallback != null) {
455460
instrumentationCallback.onRedirectorCallInserted(link, redirectCallU, redirectMethod);
461+
}
456462

457463
// remove the real ICC methods call stmt
458464
// link.getFromSM().retrieveActiveBody().getUnits().remove(link.getFromU());

soot-infoflow-android/src/soot/jimple/infoflow/android/source/ConfigurationBasedCategoryFilter.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,24 @@ public SourceSinkType filter(CategoryDefinition category, SourceSinkType sourceS
6262
CategoryMode sourceMode = config.getSourceCategoriesAndModes().get(category);
6363
CategoryMode sinkMode = config.getSinkCategoriesAndModes().get(category);
6464

65-
if (config.getSourceFilterMode() == SourceSinkFilterMode.UseAllButExcluded) {
66-
if (sourceSinkType == SourceSinkType.Source || sourceSinkType == SourceSinkType.Both)
65+
if (sourceSinkType == SourceSinkType.Source || sourceSinkType == SourceSinkType.Both) {
66+
if (config.getSourceFilterMode() == SourceSinkFilterMode.UseAllButExcluded) {
6767
if (sourceMode != null && sourceMode == CategoryMode.Exclude)
6868
sourceSinkType = sourceSinkType.removeType(SourceSinkType.Source);
69-
if (sourceSinkType == SourceSinkType.Sink || sourceSinkType == SourceSinkType.Both)
70-
if (sinkMode != null && sinkMode == CategoryMode.Exclude)
71-
sourceSinkType = sourceSinkType.removeType(SourceSinkType.Sink);
72-
} else if (config.getSourceFilterMode() == SourceSinkFilterMode.UseOnlyIncluded) {
73-
if (sourceSinkType == SourceSinkType.Source || sourceSinkType == SourceSinkType.Both)
69+
} else if (config.getSourceFilterMode() == SourceSinkFilterMode.UseOnlyIncluded) {
7470
if (sourceMode == null || sourceMode != CategoryMode.Include)
7571
sourceSinkType = sourceSinkType.removeType(SourceSinkType.Source);
76-
if (sourceSinkType == SourceSinkType.Sink || sourceSinkType == SourceSinkType.Both)
77-
if (sourceMode == null || sinkMode != CategoryMode.Include)
72+
}
73+
}
74+
75+
if (sourceSinkType == SourceSinkType.Sink || sourceSinkType == SourceSinkType.Both) {
76+
if (config.getSinkFilterMode() == SourceSinkFilterMode.UseAllButExcluded) {
77+
if (sinkMode != null && sinkMode == CategoryMode.Exclude)
78+
sourceSinkType = sourceSinkType.removeType(SourceSinkType.Sink);
79+
} else if (config.getSinkFilterMode() == SourceSinkFilterMode.UseOnlyIncluded) {
80+
if (sinkMode == null || sinkMode != CategoryMode.Include)
7881
sourceSinkType = sourceSinkType.removeType(SourceSinkType.Sink);
82+
}
7983
}
8084

8185
return sourceSinkType;

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/data/summary/MethodFlow.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,13 @@ public String toString() {
242242
}
243243

244244
public boolean getIgnoreTypes() {
245-
if (ignoreTypes == null)
245+
if (ignoreTypes == null) {
246+
if (typeChecking != null && !typeChecking.booleanValue()) {
247+
if ("java.lang.Object[]".equals(to.getLastFieldType()))
248+
return true;
249+
}
246250
return false;
251+
}
247252
return ignoreTypes;
248253
}
249254

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/taintWrappers/SummaryTaintWrapper.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,15 +1689,15 @@ private Taint addSinkTaint(MethodFlow flow, Taint taint, GapDefinition gap) {
16891689
if (flowSink.getType() == SourceSinkType.GapBaseObject && remainingFields != null && !remainingFields.isEmpty())
16901690
sourceSinkType = SourceSinkType.Field;
16911691

1692-
// Compute the new base type
1693-
Type newBaseType = TypeUtils.getMorePreciseType(taintType, sinkType);
1694-
if (newBaseType == null)
1695-
newBaseType = sinkType;
16961692
String sBaseType = sinkType == null ? null : "" + sinkType;
1697-
1698-
// Set the correct type. In case x -> b.x, the new type is not the type
1699-
// of b, but of the field x.
17001693
if (!flow.getIgnoreTypes()) {
1694+
// Compute the new base type
1695+
Type newBaseType = TypeUtils.getMorePreciseType(taintType, sinkType);
1696+
if (newBaseType == null)
1697+
newBaseType = sinkType;
1698+
1699+
// Set the correct type. In case x -> b.x, the new type is not the type
1700+
// of b, but of the field x.
17011701
if (flowSink.hasAccessPath()) {
17021702
if (appendedFields != null)
17031703
appendedFields = appendedFields.updateFieldType(flowSink.getAccessPathLength() - 1,

soot-infoflow/src/soot/jimple/infoflow/codeOptimization/InterproceduralConstantValuePropagator.java

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import soot.jimple.infoflow.entryPointCreators.BaseEntryPointCreator;
5959
import soot.jimple.infoflow.entryPointCreators.IEntryPointCreator;
6060
import soot.jimple.infoflow.entryPointCreators.SimulatedCodeElementTag;
61+
import soot.jimple.infoflow.solver.cfg.IInfoflowCFG;
6162
import soot.jimple.infoflow.sourcesSinks.manager.ISourceSinkManager;
6263
import soot.jimple.infoflow.taintWrappers.ITaintPropagationWrapper;
6364
import soot.jimple.infoflow.util.SystemClassHandler;
@@ -127,7 +128,7 @@ public InterproceduralConstantValuePropagator(InfoflowManager manager) {
127128
public InterproceduralConstantValuePropagator(InfoflowManager manager, Collection<SootMethod> excludedMethods,
128129
ISourceSinkManager sourceSinkManager, ITaintPropagationWrapper taintWrapper) {
129130
this.manager = manager;
130-
this.excludedMethods = new HashSet<SootMethod>(excludedMethods);
131+
this.excludedMethods = new HashSet<>(excludedMethods);
131132
this.sourceSinkManager = sourceSinkManager;
132133
this.taintWrapper = taintWrapper;
133134
}
@@ -256,7 +257,7 @@ protected void internalTransform(String phaseName, Map<String, String> options)
256257
continue;
257258

258259
boolean allCalleesRemoved = true;
259-
Set<SootClass> exceptions = new HashSet<SootClass>();
260+
Set<SootClass> exceptions = new HashSet<>();
260261
for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(s); edgeIt.hasNext();) {
261262
Edge edge = edgeIt.next();
262263
SootMethod callee = edge.tgt();
@@ -392,10 +393,11 @@ private boolean typeSupportsConstants(Type returnType) {
392393
* @param sm The method whose value to propagate
393394
*/
394395
private void propagateReturnValueIntoCallers(SootMethod sm) {
396+
final IInfoflowCFG icfg = manager.getICFG();
395397
// We need to make sure that all exit nodes agree on the same
396398
// constant value
397399
Constant value = null;
398-
for (Unit retSite : manager.getICFG().getEndPointsOf(sm)) {
400+
for (Unit retSite : icfg.getEndPointsOf(sm)) {
399401
// Skip exceptional exits
400402
if (!(retSite instanceof ReturnStmt))
401403
continue;
@@ -411,7 +413,7 @@ private void propagateReturnValueIntoCallers(SootMethod sm) {
411413

412414
// Propagate the return value into the callers
413415
if (value != null)
414-
for (Unit callSite : manager.getICFG().getCallersOf(sm))
416+
for (Unit callSite : icfg.getCallersOf(sm))
415417
if (callSite instanceof AssignStmt) {
416418
AssignStmt assign = (AssignStmt) callSite;
417419

@@ -427,13 +429,13 @@ private void propagateReturnValueIntoCallers(SootMethod sm) {
427429

428430
// Make sure that we don't access anything we have already
429431
// removed
430-
SootMethod caller = manager.getICFG().getMethodOf(assign);
432+
SootMethod caller = icfg.getMethodOf(assign);
431433
if (caller == null || !caller.getActiveBody().getUnits().contains(assign))
432434
continue;
433435

434436
// If the call site has multiple callees, we cannot
435437
// propagate a single constant
436-
Collection<SootMethod> callees = manager.getICFG().getCalleesOfCallAt(callSite);
438+
Collection<SootMethod> callees = icfg.getCalleesOfCallAt(callSite);
437439
if (callees != null && callees.size() > 1)
438440
continue;
439441

@@ -478,7 +480,7 @@ private void propagateReturnValueIntoCallers(SootMethod sm) {
478480
}
479481

480482
private void fixExceptions(SootMethod caller, Unit callSite) {
481-
fixExceptions(caller, callSite, new HashSet<SootClass>());
483+
fixExceptions(caller, callSite, new HashSet<>());
482484
}
483485

484486
private void fixExceptions(SootMethod caller, Unit callSite, Set<SootClass> doneSet) {
@@ -493,6 +495,7 @@ private void fixExceptions(SootMethod caller, Unit callSite, Set<SootClass> done
493495
if (exceptionClass == null) {
494496
exceptionClass = Scene.v().makeSootClass("FLOWDROID_EXCEPTIONS", Modifier.PUBLIC);
495497
exceptionClass.setSuperclass(Scene.v().getSootClass("java.lang.Object"));
498+
exceptionClass.addTag(SimulatedCodeElementTag.TAG);
496499
Scene.v().addClass(exceptionClass);
497500
}
498501

@@ -541,9 +544,10 @@ protected SootMethod createDummyMainInternal() {
541544
protected void createEmptyMainMethod() {
542545
// Make sure that we don't end up with duplicate method names
543546
int methodIdx = exceptionThrowers.size();
547+
String baseName = "throw_" + t.getException().getName().replaceAll("\\W+", "_") + "_";
544548
String methodName;
545549
do {
546-
methodName = "throw" + methodIdx++;
550+
methodName = baseName + methodIdx++;
547551
} while (exceptionClass.declaresMethodByName(methodName));
548552

549553
// Create the new method
@@ -582,6 +586,7 @@ public Collection<SootField> getAdditionalFields() {
582586
Stmt throwCall = Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(thrower.makeRef()));
583587
throwCall.addTag(SimulatedCodeElementTag.TAG);
584588
caller.getActiveBody().getUnits().insertBefore(throwCall, callSite);
589+
585590
}
586591
}
587592

@@ -594,7 +599,7 @@ public Collection<SootField> getAdditionalFields() {
594599
* side-effects or calls a sink method, otherwise false.
595600
*/
596601
private boolean hasSideEffectsOrCallsSink(SootMethod method) {
597-
return hasSideEffectsOrCallsSink(method, new HashSet<SootMethod>());
602+
return hasSideEffectsOrCallsSink(method, new HashSet<>());
598603
}
599604

600605
/**
@@ -778,7 +783,7 @@ private boolean methodIsAndroidStub(SootMethod method) {
778783
// Check for super class constructor invocation
779784
if (!(method.getDeclaringClass().hasSuperclass()
780785
&& callee.getDeclaringClass() == method.getDeclaringClass().getSuperclass()
781-
&& callee.getName().equals("<init>")))
786+
&& callee.isConstructor()))
782787
return false;
783788
} else if (!(u instanceof ThrowStmt))
784789
return false;
@@ -794,7 +799,11 @@ private boolean methodIsAndroidStub(SootMethod method) {
794799
* @param sm The method for which to look for call sites.
795800
*/
796801
private void propagateConstantsIntoCallee(SootMethod sm) {
797-
Collection<Unit> callSites = manager.getICFG().getCallersOf(sm);
802+
803+
// icfg field is final in InfoflowManager, hence it can't change
804+
// and we can cache it here so we don't have to retrieve it again and again.
805+
final IInfoflowCFG icfg = manager.getICFG();
806+
Collection<Unit> callSites = icfg.getCallersOf(sm);
798807
if (callSites.isEmpty())
799808
return;
800809

@@ -807,9 +816,14 @@ private void propagateConstantsIntoCallee(SootMethod sm) {
807816
boolean hasCallSites = false;
808817
for (Unit callSite : callSites) {
809818
// If this call site is in an excluded method, we ignore it
810-
if (excludedMethods != null && manager.getICFG().isReachable(callSite)
811-
&& excludedMethods.contains(manager.getICFG().getMethodOf(callSite)))
812-
continue;
819+
if (excludedMethods != null && icfg.isReachable(callSite)) {
820+
SootMethod caller = icfg.getMethodOf(callSite);
821+
// synthetic methods e.g. created by FlowDroid are excluded by default
822+
if (excludedMethods.contains(caller) || caller.hasTag(SimulatedCodeElementTag.TAG_NAME)) {
823+
logger.trace("Ignoring calls from {}", caller);
824+
continue;
825+
}
826+
}
813827

814828
// We do not support special edges that do not provide a 1:1 argument mapping
815829
InvokeExpr iiExpr = ((Stmt) callSite).getInvokeExpr();
@@ -821,7 +835,7 @@ private void propagateConstantsIntoCallee(SootMethod sm) {
821835
// If we have a reflective call site, we never have constant
822836
// arguments, because
823837
// they are always passed in using an array
824-
if (manager.getICFG().isReflectiveCallSite(callSite)) {
838+
if (icfg.isReflectiveCallSite(callSite)) {
825839
for (int i = 0; i < isConstant.length; i++)
826840
isConstant[i] = false;
827841
} else {
@@ -837,8 +851,9 @@ private void propagateConstantsIntoCallee(SootMethod sm) {
837851
isConstant[i] = false;
838852
else
839853
values[i] = (Constant) argVal;
840-
} else
854+
} else {
841855
isConstant[i] = false;
856+
}
842857
}
843858
}
844859
}
@@ -856,7 +871,7 @@ private void propagateConstantsIntoCallee(SootMethod sm) {
856871
sm.getActiveBody().getUnits().insertBefore(assignConst, point);
857872

858873
if (inserted == null)
859-
inserted = new ArrayList<Unit>();
874+
inserted = new ArrayList<>();
860875
inserted.add(assignConst);
861876
}
862877
}
@@ -869,7 +884,7 @@ private void propagateConstantsIntoCallee(SootMethod sm) {
869884

870885
// This might lead to more opportunities of constant propagation
871886
for (Unit u : sm.getActiveBody().getUnits())
872-
for (SootMethod callee : manager.getICFG().getCalleesOfCallAt(u))
887+
for (SootMethod callee : icfg.getCalleesOfCallAt(u))
873888
checkAndAddMethod(callee);
874889
}
875890
}

0 commit comments

Comments
 (0)