Skip to content

Commit 6c47ad3

Browse files
authored
Merge pull request #618 from timll/develop
Various fixes
2 parents bea8788 + fa5ee1c commit 6c47ad3

File tree

19 files changed

+168
-240
lines changed

19 files changed

+168
-240
lines changed

soot-infoflow-integration/test/soot/jimple/infoflow/integration/test/junit/AndroidRegressionTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,15 @@ public void testKotlinAppWithCollections() throws IOException {
8888
Assert.assertEquals(4, results.size());
8989
Assert.assertEquals(4, results.getResultSet().size());
9090
}
91+
92+
/**
93+
* Tests that the CallToReturnFunction does not pass on taints that were killed
94+
* by a taint wrapper that marked the method as exclusive.
95+
*/
96+
@Test
97+
public void testMapClear() throws XmlPullParserException, IOException {
98+
SetupApplication app = initApplication("testAPKs/MapClearTest.apk");
99+
InfoflowResults results = app.runInfoflow("../soot-infoflow-android/SourcesAndSinks.txt");
100+
Assert.assertEquals(0, results.size());
101+
}
91102
}
3.56 MB
Binary file not shown.

soot-infoflow-summaries/schema/ClassSummary.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
</xs:sequence>
3636
<xs:attribute name="fileFormatVersion" type="xs:int" />
3737
<xs:attribute name="isInterface" type="xs:boolean" />
38+
<xs:attribute name="isExclusive" type="xs:boolean" />
3839
</xs:complexType>
3940
</xs:element>
4041

soot-infoflow-summaries/src/soot/jimple/infoflow/methodSummary/generator/SummaryGenerator.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import soot.jimple.infoflow.nativeCallHandler.INativeCallHandler;
5454
import soot.jimple.infoflow.results.InfoflowResults;
5555
import soot.jimple.infoflow.solver.cfg.IInfoflowCFG;
56-
import soot.jimple.infoflow.taintWrappers.TaintWrapperList;
5756
import soot.options.Options;
5857

5958
/**
@@ -75,8 +74,8 @@ public class SummaryGenerator {
7574

7675
protected List<String> substitutedWith = new LinkedList<String>();
7776

78-
protected SummaryTaintWrapper fallbackWrapper;
79-
protected boolean fallbackWrapperInitialized = false;
77+
protected SummaryTaintWrapper summaryTaintWrapper;
78+
protected boolean summaryTaintWrapperInitialized = false;
8079
protected MemorySummaryProvider onFlySummaryProvider = null;
8180

8281
public SummaryGenerator() {
@@ -86,10 +85,10 @@ public SummaryGenerator() {
8685
/**
8786
* Initializes the fallback taint wrapper
8887
*/
89-
protected void initializeFallbackWrapper() {
90-
if (fallbackWrapperInitialized)
88+
protected void initializeSummaryTaintWrapper() {
89+
if (summaryTaintWrapperInitialized)
9190
return;
92-
fallbackWrapperInitialized = true;
91+
summaryTaintWrapperInitialized = true;
9392

9493
try {
9594
// Do we want to integrate summaries on the fly?
@@ -113,7 +112,7 @@ protected void initializeFallbackWrapper() {
113112

114113
// Combine our summary providers
115114
IMethodSummaryProvider provider = new MergingSummaryProvider(innerProviders);
116-
fallbackWrapper = new SummaryTaintWrapper(provider);
115+
summaryTaintWrapper = new SummaryTaintWrapper(provider);
117116
} catch (Exception e) {
118117
LoggerFactory.getLogger(getClass()).error(
119118
"An error occurred while loading the fallback taint wrapper, proceeding without fallback", e);
@@ -125,9 +124,9 @@ protected void initializeFallbackWrapper() {
125124
* new summaries. Call this method after changing pre-existing summary files on
126125
* disk.
127126
*/
128-
public void releaseFallbackTaintWrapper() {
129-
this.fallbackWrapper = null;
130-
this.fallbackWrapperInitialized = false;
127+
public void releaseSummaryTaintWrapper() {
128+
this.summaryTaintWrapper = null;
129+
this.summaryTaintWrapperInitialized = false;
131130
}
132131

133132
/**
@@ -625,7 +624,7 @@ protected MethodSummaries createMethodSummary(String classpath, final String met
625624
final IGapManager gapManager, final ResultsAvailableHandler resultHandler) {
626625
// We need to construct a fallback taint wrapper based on the current
627626
// configuration
628-
initializeFallbackWrapper();
627+
initializeSummaryTaintWrapper();
629628

630629
logger.info(String.format("Computing method summary for %s...", methodSig));
631630
long nanosBeforeMethod = System.nanoTime();
@@ -761,8 +760,12 @@ protected ISummaryInfoflow initInfoflow(MethodSummaries summaries, IGapManager g
761760
else
762761
iFlow.setNativeCallHandler(new SummaryNativeCallHandler(nativeCallHandler));
763762

764-
final SummaryGenerationTaintWrapper summaryWrapper = createTaintWrapper(summaries, gapManager);
765-
iFlow.setTaintWrapper(new TaintWrapperList(fallbackWrapper, summaryWrapper));
763+
final SummaryGenerationTaintWrapper summaryGenWrapper = createTaintWrapper(summaries, gapManager);
764+
// We only want to compute summaries for methods we do not have summaries. Thus, we register the
765+
// summary generation wrapper as a fallback to the SummaryTaintWrapper such that it is only queried
766+
// when the SummaryTaintWrapper doesn't know the method.
767+
summaryTaintWrapper.setFallbackTaintWrapper(summaryGenWrapper);
768+
iFlow.setTaintWrapper(summaryTaintWrapper);
766769

767770
// Set the Soot configuration
768771
if (sootConfig == null)

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.List;
88
import java.util.Set;
99
import java.util.concurrent.atomic.AtomicInteger;
10+
import java.util.function.Function;
1011
import java.util.regex.Matcher;
1112
import java.util.regex.Pattern;
1213

@@ -526,11 +527,8 @@ public Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstractio
526527
return Collections.singleton(taintedAbs);
527528
else {
528529
reportMissingSummary(callee, stmt, taintedAbs);
529-
if (fallbackWrapper == null)
530-
return null;
531-
else {
532-
Set<Abstraction> fallbackTaints = fallbackWrapper.getTaintsForMethod(stmt, d1, taintedAbs);
533-
return fallbackTaints;
530+
if (fallbackWrapper != null) {
531+
return fallbackWrapper.getTaintsForMethod(stmt, d1, taintedAbs);
534532
}
535533
}
536534
}
@@ -1594,14 +1592,22 @@ public boolean isExclusive(Stmt stmt, Abstraction taintedPath) {
15941592

15951593
@Override
15961594
public boolean supportsCallee(SootMethod method) {
1597-
// Check whether we directly support that class. We assume that if we
1598-
// have some summary for that class, we have all summaries for that
1599-
// class.
1595+
// Check whether we directly support that class
16001596
SootClass declClass = method.getDeclaringClass();
1601-
if (declClass != null && flows.supportsClass(declClass.getName()))
1597+
if (declClass == null)
1598+
return false;
1599+
1600+
ClassMethodSummaries cms = flows.getClassFlows(declClass.getName());
1601+
if (cms == null)
1602+
return false;
1603+
1604+
// We assume for exclusive classes that we have all summaries for that class.
1605+
if (cms.isExclusiveForClass())
16021606
return true;
16031607

1604-
return false;
1608+
// Otherwise, we check whether we have a summary for the method.
1609+
MethodSummaries summaries = cms.getMethodSummaries().filterForMethod(method.getSubSignature());
1610+
return summaries != null && !summaries.isEmpty();
16051611
}
16061612

16071613
@Override
@@ -1757,12 +1763,9 @@ public Set<Abstraction> getInverseTaintsForMethod(Stmt stmt, Abstraction d1, Abs
17571763
ClassSummaries flowsInCallees = getFlowSummariesForMethod(stmt, method, taintedAbs, null);
17581764

17591765
// If we have no data flows, we can abort early
1760-
if (flowsInCallees.isEmpty()) {
1766+
if (flowsInCallees.isEmpty())
17611767
if (fallbackWrapper != null && fallbackWrapper instanceof IReversibleTaintWrapper)
17621768
return ((IReversibleTaintWrapper) fallbackWrapper).getInverseTaintsForMethod(stmt, d1, taintedAbs);
1763-
else
1764-
return null;
1765-
}
17661769

17671770
// Create a level-0 propagator for the initially tainted access path
17681771
ByReferenceBoolean killIncomingTaint = new ByReferenceBoolean();

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public void read(Reader reader, ClassMethodSummaries summaries)
9090
// not call setInterface()!
9191
if (isInterface != null && !isInterface.isEmpty())
9292
summaries.setInterface(isInterface.equals(XMLConstants.VALUE_TRUE));
93+
94+
String isExclusive = getAttributeByName(xmlreader, XMLConstants.ATTRIBUTE_IS_EXCLUSIVE);
95+
if (isExclusive != null && !isExclusive.isEmpty())
96+
summaries.setExclusiveForClass(isExclusive.equals(XMLConstants.VALUE_TRUE));
9397
} else if (localName.equals(XMLConstants.TREE_METHODS) && xmlreader.isStartElement()) {
9498
if (state == State.summary)
9599
state = State.methods;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class XMLConstants {
4141
public static final String ATTRIBUTE_MATCH_STRICT = "matchStrict";
4242
public static final String ATTRIBUTE_NAME = "name";
4343
public static final String ATTRIBUTE_SUPERCLASS = "superClass";
44+
public static final String ATTRIBUTE_IS_EXCLUSIVE = "isExclusive";
4445

4546
public static final String VALUE_TRUE = "true";
4647
public static final String VALUE_FALSE = "false";
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" ?>
2+
<summary fileFormatVersion="101">
3+
<hierarchy superClass="kotlin.collections.CollectionsKt___CollectionsKt" />
4+
</summary>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" ?>
2+
<summary fileFormatVersion="101" isExclusive="false">
3+
<methods>
4+
<method id="java.lang.String joinToString$default(java.lang.Iterable,java.lang.CharSequence,java.lang.CharSequence,java.lang.CharSequence,int,java.lang.CharSequence,kotlin.jvm.functions.Function1,int,java.lang.Object)">
5+
<flows>
6+
<flow isAlias="false" typeChecking="false" cutSubFields="true">
7+
<from sourceSinkType="Parameter" ParameterIndex="0"
8+
AccessPath="[java.util.Collection: java.lang.Object[] innerArray]"
9+
AccessPathTypes="[java.lang.Object[]]" />
10+
<to sourceSinkType="Return" />
11+
</flow>
12+
</flows>
13+
</method>
14+
</methods>
15+
</summary>

soot-infoflow-summaries/test/soot/jimple/infoflow/test/methodSummary/ApiClassClient.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
import java.io.ObjectOutputStream;
55
import java.io.ObjectOutputStream.PutField;
66
import java.math.BigInteger;
7-
import java.util.HashMap;
8-
import java.util.Map;
7+
import java.util.*;
98

109
public class ApiClassClient {
1110
public Object source() {
@@ -302,4 +301,12 @@ public void mapToString() {
302301
char c = str.charAt(2);
303302
sink(c);
304303
}
304+
305+
public void iterator() {
306+
List<String> lst = new ArrayList<>();
307+
lst.add(stringSource());
308+
Iterator<String> it = lst.iterator();
309+
if (it.hasNext())
310+
sink(it.next());
311+
}
305312
}

0 commit comments

Comments
 (0)