Skip to content

Commit c480632

Browse files
committed
allow for directory-based classpaths as input to StubDroid, fixed various smaller bugs, and corrected access path cut-offs to be optional
1 parent f4c4eed commit c480632

File tree

6 files changed

+47
-28
lines changed

6 files changed

+47
-28
lines changed

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/Main.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public void run(final String[] args) throws FileNotFoundException, XMLStreamExce
124124
generator.getConfig().setExcludes(excludes);
125125

126126
// Set optional settings
127-
conifgureOptionalSettings(cmd, generator);
127+
configureOptionalSettings(cmd, generator);
128128

129129
// Configure the output directory
130130
if (!toAnalyze.exists()) {
@@ -149,6 +149,13 @@ public boolean accept(File dir, String name) {
149149
System.out.println(String.format("Jar %d of %d: %s", c + 1, files.length, f));
150150
createSummaries(generator, classesToAnalyze, forceOverwrite, f, outputFolder);
151151
}
152+
153+
// If we don't have any JAR files, the target may be a normal classpath with
154+
// Java class files
155+
if (files.length == 0) {
156+
System.out.println(String.format("Analyzing directory %s...", toAnalyze.getAbsolutePath()));
157+
createSummaries(generator, classesToAnalyze, forceOverwrite, toAnalyze, outputFolder);
158+
}
152159
} else {
153160
createSummaries(generator, classesToAnalyze, forceOverwrite, toAnalyze, outputFolder);
154161
}
@@ -167,7 +174,7 @@ public boolean accept(File dir, String name) {
167174
* @param cmd The command-line options
168175
* @param generator The summary generator
169176
*/
170-
protected void conifgureOptionalSettings(CommandLine cmd, SummaryGenerator generator) {
177+
protected void configureOptionalSettings(CommandLine cmd, SummaryGenerator generator) {
171178
{
172179
int repeatCount = Integer.parseInt(cmd.getOptionValue(OPTION_REPEAT, "-1"));
173180
if (repeatCount > 0)

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

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class MethodFlow extends AbstractMethodSummary {
2020
private final FlowSource from;
2121
private final FlowSink to;
2222
private final boolean isAlias;
23-
private final boolean typeChecking;
23+
private final Boolean typeChecking;
2424
private final Boolean cutSubFields;
2525

2626
/**
@@ -38,7 +38,7 @@ public class MethodFlow extends AbstractMethodSummary {
3838
* field "b" will not appended to the sink if this option is
3939
* enabled.
4040
*/
41-
public MethodFlow(String methodSig, FlowSource from, FlowSink to, boolean isAlias, boolean typeChecking,
41+
public MethodFlow(String methodSig, FlowSource from, FlowSink to, boolean isAlias, Boolean typeChecking,
4242
Boolean cutSubFields) {
4343
super(methodSig);
4444
this.from = from;
@@ -124,7 +124,7 @@ public boolean isAlias() {
124124
* @return True if type checking shall be performed before applying this method
125125
* flow, otherwise false
126126
*/
127-
public boolean getTypeChecking() {
127+
public Boolean getTypeChecking() {
128128
return this.typeChecking;
129129
}
130130

@@ -212,7 +212,10 @@ public boolean equals(Object obj) {
212212
return false;
213213
} else if (!to.equals(other.to))
214214
return false;
215-
if (typeChecking != other.typeChecking)
215+
if (typeChecking == null) {
216+
if (other.typeChecking != null)
217+
return false;
218+
} else if (!typeChecking.equals(other.typeChecking))
216219
return false;
217220
return true;
218221
}
@@ -225,7 +228,7 @@ public int hashCode() {
225228
result = prime * result + ((from == null) ? 0 : from.hashCode());
226229
result = prime * result + (isAlias ? 1231 : 1237);
227230
result = prime * result + ((to == null) ? 0 : to.hashCode());
228-
result = prime * result + (typeChecking ? 1231 : 1237);
231+
result = prime * result + ((typeChecking == null) ? 0 : typeChecking.hashCode());
229232
return result;
230233
}
231234

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public boolean isEmpty() {
150150
public AccessPathFragment append(AccessPathFragment toAppend) {
151151
// If only one of the two operands contains actual data, we simply take that
152152
// object and don't need to append anything
153-
if (toAppend == null) {
153+
if (toAppend == null || toAppend.isEmpty()) {
154154
if (this.isEmpty())
155155
return null;
156156
return this;

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

+23-16
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,10 @@ private AccessPath createAccessPathInMethod(Taint t, SootMethod sm) {
742742

743743
@Override
744744
public Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstraction taintedAbs) {
745+
746+
if (stmt.toString().contains("toByteArray"))
747+
System.out.println("x");
748+
745749
// We only care about method invocations
746750
if (!stmt.containsInvokeExpr())
747751
return Collections.singleton(taintedAbs);
@@ -751,8 +755,8 @@ public Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstractio
751755
ByReferenceBoolean classSupported = new ByReferenceBoolean(false);
752756

753757
// Compute the wrapper taints for the current method
754-
Set<AccessPath> res = computeTaintsForMethod(stmt, d1, taintedAbs, stmt.getInvokeExpr().getMethod(),
755-
killIncomingTaint, classSupported);
758+
final SootMethod callee = stmt.getInvokeExpr().getMethod();
759+
Set<AccessPath> res = computeTaintsForMethod(stmt, d1, taintedAbs, callee, killIncomingTaint, classSupported);
756760

757761
// Create abstractions from the access paths
758762
if (res != null && !res.isEmpty()) {
@@ -765,10 +769,9 @@ public Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstractio
765769
// If we have no data flows, we can abort early
766770
if (!killIncomingTaint.value && (resAbs == null || resAbs.isEmpty())) {
767771
wrapperMisses.incrementAndGet();
768-
SootMethod method = stmt.getInvokeExpr().getMethod();
769772

770773
if (!classSupported.value)
771-
reportMissingMethod(method);
774+
reportMissingMethod(callee);
772775

773776
if (classSupported.value)
774777
return Collections.singleton(taintedAbs);
@@ -897,19 +900,21 @@ private Set<AccessPath> applyFlowsIterative(MethodSummaries flowsInCallee, List<
897900
// implementations in the application code
898901
if ((flowsInTarget == null || flowsInTarget.isEmpty()) && curGap != null) {
899902
SootMethod callee = Scene.v().grabMethod(curGap.getSignature());
900-
if (callee != null)
901-
for (SootMethod implementor : getAllImplementors(callee))
903+
if (callee != null) {
904+
for (SootMethod implementor : getAllImplementors(callee)) {
902905
if (implementor.getDeclaringClass().isConcrete() && !implementor.getDeclaringClass().isPhantom()
903906
&& implementor.isConcrete()) {
904907
Set<AccessPathPropagator> implementorPropagators = spawnAnalysisIntoClientCode(implementor,
905908
curPropagator);
906909
if (implementorPropagators != null)
907910
workList.addAll(implementorPropagators);
908911
}
912+
}
913+
}
909914
}
910915

911916
// Apply the flow summaries for other libraries
912-
if (flowsInTarget != null && !flowsInTarget.isEmpty())
917+
if (flowsInTarget != null && !flowsInTarget.isEmpty()) {
913918
for (MethodFlow flow : flowsInTarget) {
914919
// Apply the flow summary
915920
AccessPathPropagator newPropagator = applyFlow(flow, curPropagator);
@@ -947,6 +952,7 @@ private Set<AccessPath> applyFlowsIterative(MethodSummaries flowsInCallee, List<
947952
workList.add(backwardsPropagator);
948953
}
949954
}
955+
}
950956
}
951957
return res;
952958
}
@@ -1610,7 +1616,7 @@ private Taint addSinkTaint(MethodFlow flow, Taint taint, GapDefinition gap) {
16101616
final AbstractFlowSinkSource flowSource = flow.source();
16111617
final AbstractFlowSinkSource flowSink = flow.sink();
16121618
final boolean taintSubFields = flow.sink().taintSubFields();
1613-
final boolean checkTypes = flow.getTypeChecking();
1619+
final Boolean checkTypes = flow.getTypeChecking();
16141620

16151621
AccessPathFragment remainingFields = cutSubFields(flow, getRemainingFields(flowSource, taint));
16161622
AccessPathFragment appendedFields = AccessPathFragment.append(flowSink.getAccessPath(), remainingFields);
@@ -1620,16 +1626,13 @@ private Taint addSinkTaint(MethodFlow flow, Taint taint, GapDefinition gap) {
16201626
Type sinkType = TypeUtils.getTypeFromString(getAssignmentType(flowSink));
16211627
Type taintType = TypeUtils.getTypeFromString(getAssignmentType(taint, lastCommonAPIdx - 1));
16221628

1623-
if (checkTypes) {
1624-
// For type checking, we need types
1625-
if (sinkType == null || taintType == null)
1626-
return null;
1627-
1629+
// For type checking, we need types
1630+
if ((checkTypes == null || checkTypes.booleanValue()) && sinkType != null && taintType != null) {
16281631
// If we taint something in the base object, its type must match. We
16291632
// might have a taint for "a" in o.add(a) and need to check whether
16301633
// "o" matches the expected type in our summary.
16311634
if (!(sinkType instanceof PrimType) && !isCastCompatible(taintType, sinkType)
1632-
&& flowSink.getType() == SourceSinkType.Field && !checkTypes) {
1635+
&& flowSink.getType() == SourceSinkType.Field) {
16331636
// If the target is an array, the value might also flow into an
16341637
// element
16351638
boolean found = false;
@@ -1703,8 +1706,12 @@ protected AccessPathFragment cutSubFields(MethodFlow flow, AccessPathFragment ac
17031706
*/
17041707
protected boolean isCutSubFields(MethodFlow flow) {
17051708
Boolean cut = flow.getCutSubFields();
1706-
if (cut == null)
1707-
return !flow.getTypeChecking();
1709+
Boolean typeChecking = flow.getTypeChecking();
1710+
if (cut == null) {
1711+
if (typeChecking != null)
1712+
return !typeChecking.booleanValue();
1713+
return false;
1714+
}
17081715
return cut.booleanValue();
17091716
}
17101717

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/xml/SummaryReader.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void read(Reader reader, ClassMethodSummaries summaries)
6868
String currentMethod = "";
6969
int currentID = -1;
7070
boolean isAlias = false;
71-
boolean typeChecking = true;
71+
Boolean typeChecking = null;
7272
Boolean cutSubfields = null;
7373

7474
State state = State.summary;
@@ -105,12 +105,14 @@ public void read(Reader reader, ClassMethodSummaries summaries)
105105
state = State.flow;
106106
String sAlias = getAttributeByName(xmlreader, XMLConstants.ATTRIBUTE_IS_ALIAS);
107107
isAlias = sAlias != null && sAlias.equals(XMLConstants.VALUE_TRUE);
108+
108109
String sTypeChecking = getAttributeByName(xmlreader, XMLConstants.ATTRIBUTE_TYPE_CHECKING);
109-
if (sTypeChecking != null)
110+
if (sTypeChecking != null && !sTypeChecking.isEmpty())
110111
typeChecking = sTypeChecking.equals(XMLConstants.VALUE_TRUE);
112+
111113
String sCutSubfields = getAttributeByName(xmlreader, XMLConstants.ATTRIBUTE_CUT_SUBFIELDS);
112114
if (sCutSubfields != null && !sCutSubfields.isEmpty())
113-
cutSubfields = sTypeChecking.equals(XMLConstants.VALUE_TRUE);
115+
cutSubfields = sCutSubfields.equals(XMLConstants.VALUE_TRUE);
114116
} else
115117
throw new SummaryXMLException();
116118
} else if (localName.equals(TREE_CLEAR) && xmlreader.isStartElement()) {

soot-infoflow-summaries/test/soot/jimple/infoflow/test/methodSummary/junit/SummaryTaintWrapperTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public void apl3Flow() {
125125
testFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void apl3Flow()>");
126126
}
127127

128-
@Test // (timeout = 30000)
128+
@Test(timeout = 30000)
129129
public void gapFlow1() {
130130
testFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void gapFlow1()>");
131131
}

0 commit comments

Comments
 (0)