Skip to content

Commit a7c94d0

Browse files
authored
Merge pull request #628 from timll/sparse
Sparse IFDS solver
2 parents c4adcd8 + 8453e26 commit a7c94d0

File tree

16 files changed

+821
-41
lines changed

16 files changed

+821
-41
lines changed

soot-infoflow-android/test/soot/jimple/infoflow/android/test/droidBench/GeneralJavaTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,8 @@ public void runTestStaticInitialization1() throws IOException, XmlPullParserExce
135135

136136
@Test(timeout=300000)
137137
public void runTestStaticInitialization2() throws IOException, XmlPullParserException {
138-
int expected = 1;
139-
if (mode == TestResultMode.FLOWDROID_BACKWARDS || mode == TestResultMode.FLOWDROID_FORWARDS)
140-
expected = 1;
141138
InfoflowResults res = analyzeAPKFile("GeneralJava/StaticInitialization2.apk");
142-
Assert.assertEquals(expected, res.size());
139+
Assert.assertEquals(1, res.size());
143140
}
144141

145142
@Test(timeout=300000)

soot-infoflow/src/soot/jimple/infoflow/AbstractInfoflow.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
import soot.jimple.infoflow.solver.memory.DefaultMemoryManagerFactory;
103103
import soot.jimple.infoflow.solver.memory.IMemoryManager;
104104
import soot.jimple.infoflow.solver.memory.IMemoryManagerFactory;
105+
import soot.jimple.infoflow.solver.sparseSolver.SparseInfoflowSolver;
105106
import soot.jimple.infoflow.sourcesSinks.manager.DefaultSourceSinkManager;
106107
import soot.jimple.infoflow.sourcesSinks.manager.IOneSourceAtATimeManager;
107108
import soot.jimple.infoflow.sourcesSinks.manager.ISourceSinkManager;
@@ -1240,6 +1241,10 @@ protected IInfoflowSolver createDataFlowSolver(InterruptableExecutor executor, A
12401241
case ContextFlowSensitive:
12411242
logger.info("Using context- and flow-sensitive solver");
12421243
return new soot.jimple.infoflow.solver.fastSolver.InfoflowSolver(problem, executor);
1244+
case SparseContextFlowSensitive:
1245+
InfoflowConfiguration.SparsePropagationStrategy opt = config.getSolverConfiguration().getSparsePropagationStrategy();
1246+
logger.info("Using sparse context-sensitive and flow-sensitive solver with sparsification " + opt.toString());
1247+
return new soot.jimple.infoflow.solver.sparseSolver.SparseInfoflowSolver(problem, executor, opt);
12431248
case FlowInsensitive:
12441249
logger.info("Using context-sensitive, but flow-insensitive solver");
12451250
return new soot.jimple.infoflow.solver.fastSolver.flowInsensitive.InfoflowSolver(problem, executor);

soot-infoflow/src/soot/jimple/infoflow/InfoflowConfiguration.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ public static enum DataFlowSolver {
125125
*/
126126
ContextFlowSensitive,
127127

128+
/**
129+
* Use a flow- and context-sensitive solver that propagates facts sparse
130+
*/
131+
SparseContextFlowSensitive,
132+
128133
/**
129134
* Use a context-sensitive, but flow-insensitive solver
130135
*/
@@ -141,6 +146,24 @@ public static enum DataFlowSolver {
141146
FineGrainedGC,
142147
}
143148

149+
/**
150+
* Enumeration containing the options for the SparseContextFlowSensitive solver
151+
*/
152+
public static enum SparsePropagationStrategy {
153+
/**
154+
* Propagate facts dense (use to test that the solver modifications don't break something)
155+
*/
156+
Dense,
157+
/**
158+
* Propagate facts sparse only based on the local
159+
*/
160+
Simple,
161+
/**
162+
* Propagate facts sparse, taking the first field of an access path into account
163+
*/
164+
Precise
165+
}
166+
144167
public static enum DataFlowDirection {
145168
/**
146169
* Use the default forwards infoflow search
@@ -971,8 +994,8 @@ public boolean equals(Object obj) {
971994
*
972995
*/
973996
public static class SolverConfiguration {
974-
975997
private DataFlowSolver dataFlowSolver = DataFlowSolver.ContextFlowSensitive;
998+
private SparsePropagationStrategy sparsePropagationStrategy = SparsePropagationStrategy.Precise;
976999
private int maxJoinPointAbstractions = 10;
9771000
private int maxCalleesPerCallSite = 75;
9781001
private int maxAbstractionPathLength = 100;
@@ -985,6 +1008,7 @@ public static class SolverConfiguration {
9851008
*/
9861009
public void merge(SolverConfiguration solverConfig) {
9871010
this.dataFlowSolver = solverConfig.dataFlowSolver;
1011+
this.sparsePropagationStrategy = solverConfig.sparsePropagationStrategy;
9881012
this.maxJoinPointAbstractions = solverConfig.maxJoinPointAbstractions;
9891013
this.maxCalleesPerCallSite = solverConfig.maxCalleesPerCallSite;
9901014
this.maxAbstractionPathLength = solverConfig.maxAbstractionPathLength;
@@ -1008,6 +1032,24 @@ public void setDataFlowSolver(DataFlowSolver solver) {
10081032
this.dataFlowSolver = solver;
10091033
}
10101034

1035+
/**
1036+
* Gets the propagation strategy used in sparsePropagation
1037+
*
1038+
* @return The data flow solver to be used for the taint analysis
1039+
*/
1040+
public SparsePropagationStrategy getSparsePropagationStrategy() {
1041+
return this.sparsePropagationStrategy;
1042+
}
1043+
1044+
/**
1045+
* Sets the data flow solver to be used for the taint analysis
1046+
*
1047+
* @param sparsePropagationStrategy The propagation strategy used for sparsification
1048+
*/
1049+
public void setSparsePropagationStrategy(SparsePropagationStrategy sparsePropagationStrategy) {
1050+
this.sparsePropagationStrategy = sparsePropagationStrategy;
1051+
}
1052+
10111053
/**
10121054
* Gets the maximum number of abstractions that shall be recorded per join
10131055
* point. In other words, enabling this option disables the recording of
@@ -1113,6 +1155,8 @@ public int hashCode() {
11131155
final int prime = 31;
11141156
int result = 1;
11151157
result = prime * result + ((dataFlowSolver == null) ? 0 : dataFlowSolver.hashCode());
1158+
if (dataFlowSolver == DataFlowSolver.SparseContextFlowSensitive)
1159+
result = prime * result + sparsePropagationStrategy.hashCode();
11161160
result = prime * result + maxCalleesPerCallSite;
11171161
result = prime * result + maxJoinPointAbstractions;
11181162
result = prime * result + maxAbstractionPathLength;
@@ -1130,6 +1174,9 @@ public boolean equals(Object obj) {
11301174
SolverConfiguration other = (SolverConfiguration) obj;
11311175
if (dataFlowSolver != other.dataFlowSolver)
11321176
return false;
1177+
if (dataFlowSolver == DataFlowSolver.SparseContextFlowSensitive)
1178+
if (sparsePropagationStrategy != other.sparsePropagationStrategy)
1179+
return false;
11331180
if (maxCalleesPerCallSite != other.maxCalleesPerCallSite)
11341181
return false;
11351182
if (maxJoinPointAbstractions != other.maxJoinPointAbstractions)

soot-infoflow/src/soot/jimple/infoflow/problems/AbstractInfoflowProblem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public boolean autoAddZero() {
139139
return false;
140140
}
141141

142-
protected boolean isCallSiteActivatingTaint(Unit callSite, Unit activationUnit) {
142+
public boolean isCallSiteActivatingTaint(Unit callSite, Unit activationUnit) {
143143
if (!manager.getConfig().getFlowSensitiveAliasing())
144144
return false;
145145

soot-infoflow/src/soot/jimple/infoflow/problems/BackwardsAliasProblem.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,6 @@ public Set<Abstraction> computeTargets(Abstraction d1, Abstraction source) {
621621
}
622622

623623
private Set<Abstraction> computeTargetsInternal(Abstraction d1, Abstraction source) {
624-
// If excluded or we do not anything about the callee,
625-
// we just pass the taint over the statement
626-
if (interproceduralCFG().getCalleesOfCallAt(callSite).isEmpty()) {
627-
return Collections.singleton(source);
628-
}
629-
630624
if (taintWrapper != null) {
631625
if (taintWrapper.isExclusive(callStmt, source)) {
632626
handOver(d1, callSite, source);
@@ -647,6 +641,12 @@ private Set<Abstraction> computeTargetsInternal(Abstraction d1, Abstraction sour
647641
}
648642
}
649643

644+
// If excluded or we do not anything about the callee,
645+
// we just pass the taint over the statement
646+
if (interproceduralCFG().getCalleesOfCallAt(callSite).isEmpty()) {
647+
return Collections.singleton(source);
648+
}
649+
650650
if (isExcluded(callee)) {
651651
return Collections.singleton(source);
652652
}

soot-infoflow/src/soot/jimple/infoflow/solver/fastSolver/IFDSSolver.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* are made available under the terms of the GNU Lesser Public License v2.1
66
* which accompanies this distribution, and is available at
77
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8-
*
8+
*
99
* Contributors:
1010
* Eric Bodden - initial API and implementation
1111
* Marc-Andre Laverdiere-Papineau - Fixed race condition
@@ -55,7 +55,7 @@
5555
/**
5656
* A solver for an {@link IFDSTabulationProblem}. This solver is not based on
5757
* the IDESolver implementation in Heros for performance reasons.
58-
*
58+
*
5959
* @param <N> The type of nodes in the interprocedural control-flow graph.
6060
* Typically {@link Unit}.
6161
* @param <D> The type of data-flow facts to be computed by the tabulation
@@ -134,9 +134,9 @@ public enum ScheduleTarget {
134134
protected boolean solverId;
135135

136136
private Set<IMemoryBoundedSolverStatusNotification> notificationListeners = new HashSet<>();
137-
private ISolverTerminationReason killFlag = null;
137+
protected ISolverTerminationReason killFlag = null;
138138

139-
private int maxCalleesPerCallSite = 75;
139+
protected int maxCalleesPerCallSite = 75;
140140
private int maxAbstractionPathLength = 100;
141141

142142
protected ISchedulingStrategy<N, D> schedulingStrategy = new DefaultSchedulingStrategy<N, D, I>(
@@ -154,14 +154,14 @@ public IFDSSolver(IFDSTabulationProblem<N, D, SootMethod, I> tabulationProblem)
154154
* Creates a solver for the given problem, constructing caches with the given
155155
* {@link CacheBuilder}. The solver must then be started by calling
156156
* {@link #solve()}.
157-
*
157+
*
158158
* @param tabulationProblem The tabulation problem to solve
159159
* @param flowFunctionCacheBuilder A valid {@link CacheBuilder} or
160160
* <code>null</code> if no caching is to be used
161161
* for flow functions.
162162
*/
163163
public IFDSSolver(IFDSTabulationProblem<N, D, SootMethod, I> tabulationProblem,
164-
@SuppressWarnings("rawtypes") CacheBuilder flowFunctionCacheBuilder) {
164+
@SuppressWarnings("rawtypes") CacheBuilder flowFunctionCacheBuilder) {
165165
if (logger.isDebugEnabled())
166166
flowFunctionCacheBuilder = flowFunctionCacheBuilder.recordStats();
167167
this.zeroValue = tabulationProblem.zeroValue();
@@ -265,7 +265,7 @@ private void runExecutorAndAwaitCompletion() {
265265
/**
266266
* Dispatch the processing of a given edge. It may be executed in a different
267267
* thread.
268-
*
268+
*
269269
* @param edge the edge to process
270270
* @param scheduleTarget
271271
*/
@@ -286,13 +286,13 @@ protected void scheduleEdgeProcessing(PathEdge<N, D> edge, ScheduleTarget schedu
286286

287287
/**
288288
* Lines 13-20 of the algorithm; processing a call site in the caller's context.
289-
*
289+
*
290290
* For each possible callee, registers incoming call edges. Also propagates
291291
* call-to-return flows and summarized callee flows within the caller.
292-
*
292+
*
293293
* @param edge an edge whose target node resembles a method call
294294
*/
295-
private void processCall(PathEdge<N, D> edge) {
295+
protected void processCall(PathEdge<N, D> edge) {
296296
final D d1 = edge.factAtSource();
297297
final N n = edge.getTarget(); // a call node; line 14...
298298

@@ -364,7 +364,7 @@ public void accept(SootMethod sCalledProcN) {
364364

365365
/**
366366
* Callback to notify derived classes that an end summary has been applied
367-
*
367+
*
368368
* @param n The call site where the end summary has been applied
369369
* @param sCalledProc The callee
370370
* @param d3 The callee-side incoming taint abstraction
@@ -373,7 +373,7 @@ protected void onEndSummaryApplied(N n, SootMethod sCalledProc, D d3) {
373373
}
374374

375375
protected void applyEndSummaryOnCall(final D d1, final N n, final D d2, Collection<N> returnSiteNs,
376-
SootMethod sCalledProcN, D d3) {
376+
SootMethod sCalledProcN, D d3) {
377377
// line 15.2
378378
Set<EndSummary<N, D>> endSumm = endSummary(sCalledProcN, d3);
379379

@@ -419,7 +419,7 @@ protected void applyEndSummaryOnCall(final D d1, final N n, final D d2, Collecti
419419

420420
/**
421421
* Computes the call flow function for the given call-site abstraction
422-
*
422+
*
423423
* @param callFlowFunction The call flow function to compute
424424
* @param d1 The abstraction at the current method's start node.
425425
* @param d2 The abstraction at the call site
@@ -431,7 +431,7 @@ protected Set<D> computeCallFlowFunction(FlowFunction<D> callFlowFunction, D d1,
431431

432432
/**
433433
* Computes the call-to-return flow function for the given call-site abstraction
434-
*
434+
*
435435
* @param callToReturnFlowFunction The call-to-return flow function to compute
436436
* @param d1 The abstraction at the current method's start
437437
* node.
@@ -444,10 +444,10 @@ protected Set<D> computeCallToReturnFlowFunction(FlowFunction<D> callToReturnFlo
444444

445445
/**
446446
* Lines 21-32 of the algorithm.
447-
*
447+
*
448448
* Stores callee-side summaries. Also, at the side of the caller, propagates
449449
* intra-procedural flows to return sites using those newly computed summaries.
450-
*
450+
*
451451
* @param edge an edge whose target node resembles a method exits
452452
*/
453453
protected void processExit(PathEdge<N, D> edge) {
@@ -543,7 +543,7 @@ protected void processExit(PathEdge<N, D> edge) {
543543
/**
544544
* Computes the return flow function for the given set of caller-side
545545
* abstractions.
546-
*
546+
*
547547
* @param retFunction The return flow function to compute
548548
* @param d1 The abstraction at the beginning of the callee
549549
* @param d2 The abstraction at the exit node in the callee
@@ -552,17 +552,17 @@ protected void processExit(PathEdge<N, D> edge) {
552552
* @return The set of caller-side abstractions at the return site
553553
*/
554554
protected Set<D> computeReturnFlowFunction(FlowFunction<D> retFunction, D d1, D d2, N callSite,
555-
Collection<D> callerSideDs) {
555+
Collection<D> callerSideDs) {
556556
return retFunction.computeTargets(d2);
557557
}
558558

559559
/**
560560
* Lines 33-37 of the algorithm. Simply propagate normal, intra-procedural
561561
* flows.
562-
*
562+
*
563563
* @param edge
564564
*/
565-
private void processNormalFlow(PathEdge<N, D> edge) {
565+
protected void processNormalFlow(PathEdge<N, D> edge) {
566566
final D d1 = edge.factAtSource();
567567
final N n = edge.getTarget();
568568
final D d2 = edge.factAtTarget();
@@ -589,7 +589,7 @@ private void processNormalFlow(PathEdge<N, D> edge) {
589589
/**
590590
* Computes the normal flow function for the given set of start and end
591591
* abstractions.
592-
*
592+
*
593593
* @param flowFunction The normal flow function to compute
594594
* @param d1 The abstraction at the method's start node
595595
* @param d2 The abstraction at the current node
@@ -601,7 +601,7 @@ protected Set<D> computeNormalFlowFunction(FlowFunction<D> flowFunction, D d1, D
601601

602602
/**
603603
* Propagates the flow further down the exploded super graph.
604-
*
604+
*
605605
* @param sourceVal the source value of the propagated summary edge
606606
* @param target the target statement
607607
* @param targetVal the target value at the target statement
@@ -652,7 +652,7 @@ protected void propagate(D sourceVal, N target, D targetVal,
652652

653653
/**
654654
* Records a jump function. The source statement is implicit.
655-
*
655+
*
656656
* @see PathEdge
657657
*/
658658
public D addFunction(PathEdge<N, D> edge) {
@@ -786,7 +786,7 @@ public boolean equals(Object obj) {
786786
* Sets the maximum number of abstractions that shall be recorded per join
787787
* point. In other words, enabling this option disables the recording of
788788
* neighbors beyond the given count.
789-
*
789+
*
790790
* @param maxJoinPointAbstractions The maximum number of abstractions per join
791791
* point, or -1 to record an arbitrary number of
792792
* join point abstractions
@@ -797,7 +797,7 @@ public void setMaxJoinPointAbstractions(int maxJoinPointAbstractions) {
797797

798798
/**
799799
* Sets the memory manager that shall be used to manage the abstractions
800-
*
800+
*
801801
* @param memoryManager The memory manager that shall be used to manage the
802802
* abstractions
803803
*/
@@ -807,7 +807,7 @@ public void setMemoryManager(IMemoryManager<D, N> memoryManager) {
807807

808808
/**
809809
* Gets the memory manager used by this solver to reduce memory consumption
810-
*
810+
*
811811
* @return The memory manager registered with this solver
812812
*/
813813
public IMemoryManager<D, N> getMemoryManager() {

soot-infoflow/src/soot/jimple/infoflow/solver/fastSolver/InfoflowSolver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
public class InfoflowSolver extends IFDSSolver<Unit, Abstraction, BiDiInterproceduralCFG<Unit, SootMethod>>
4242
implements IInfoflowSolver {
4343

44-
private IFollowReturnsPastSeedsHandler followReturnsPastSeedsHandler = null;
45-
private final AbstractInfoflowProblem problem;
44+
protected IFollowReturnsPastSeedsHandler followReturnsPastSeedsHandler = null;
45+
protected final AbstractInfoflowProblem problem;
4646

4747
public InfoflowSolver(AbstractInfoflowProblem problem, InterruptableExecutor executor) {
4848
super(problem);

0 commit comments

Comments
 (0)