Skip to content

Commit 39bbbae

Browse files
authored
Merge pull request #802 from t1mlange/develop
Fix type refinement in `SummaryTaintWrapper`
2 parents dc60e01 + cd4bf7f commit 39bbbae

File tree

4 files changed

+58
-45
lines changed

4 files changed

+58
-45
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,16 +585,23 @@ public void stringConcatTest() {
585585
}
586586

587587
public void listIrrelevantItemTest() {
588-
String secret = TelephonyManager.getDeviceId();
588+
String secret = stringSource();
589589

590590
List<Object> lvar = new ArrayList<>();
591591
Boolean bvar = true;
592592

593593
lvar.add(secret); // Adds tainted data to the list
594594
lvar.add(bvar);
595595

596-
ConnectionManager cm = new ConnectionManager();
597-
cm.publish(bvar);
596+
sink(bvar);
598597
}
599598

599+
public void testTypeNarrowing() {
600+
String secret = stringSource();
601+
// split: String -> String[]
602+
// Tests that getMorePreciseType correctly
603+
// keeps the array in the type
604+
Object[] splitted = secret.split(";");
605+
sink(splitted);
606+
}
600607
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected void testFlowForMethod(String m) {
5151
}
5252

5353
protected void testFlowForMethod(String m, int count) {
54-
54+
testFlowForMethod(m, count, null);
5555
}
5656

5757
protected void testFlowForMethod(String m, int count, Consumer<InfoflowConfiguration> configCallback) {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,12 @@ public void stringConcatTest() {
338338

339339
@Test(timeout = 30000)
340340
public void listIrrelevantItemTest() {
341-
testFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void listIrrelevantItemTest()>", 1);
341+
testNoFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void listIrrelevantItemTest()>");
342+
}
343+
344+
@Test(timeout = 30000)
345+
public void testTypeNarrowing() {
346+
testFlowForMethod("<soot.jimple.infoflow.test.methodSummary.ApiClassClient: void testTypeNarrowing()>", 1);
342347
}
343348

344349
@Test

soot-infoflow/src/soot/jimple/infoflow/typing/TypeUtils.java

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -189,66 +189,67 @@ public boolean hasCompatibleTypesForCall(AccessPath apBase, SootClass dest) {
189189
/**
190190
* Gets the more precise one of the two given types. If there is no ordering
191191
* (i.e., the two types are not cast-compatible) null is returned.
192-
*
193-
* @param tp1 The first type
194-
* @param tp2 The second type
192+
* IMPORTANT: this method is not commutative on array types. The second type must
193+
* always be the declared type, which is used to infer the array depth.
194+
* Consider, for example, the case
195+
* objArr[i] = str;
196+
* where we can narrow the type of objArr to String[]. Vice versa,
197+
* obj = strArr[i];
198+
* allows us to narrow the type of obj to String. Therefore,
199+
* getMorePreciseType(String, Object[]) should return String[] and
200+
* getMorePreciseType(Object[], String) should return String.
201+
*
202+
* @param possibleRefinement The first type
203+
* @param declType The second type
195204
* @return The more precise one of the two given types
196205
*/
197-
public Type getMorePreciseType(Type tp1, Type tp2) {
206+
public Type getMorePreciseType(Type possibleRefinement, Type declType) {
198207
final FastHierarchy fastHierarchy = scene.getOrMakeFastHierarchy();
199208

200-
if (tp1 == null)
201-
return tp2;
202-
else if (tp2 == null)
203-
return tp1;
204-
else if (tp1 == tp2)
205-
return tp1;
206-
else if (TypeUtils.isObjectLikeType(tp1))
207-
return tp2;
208-
else if (TypeUtils.isObjectLikeType(tp2))
209-
return tp1;
210-
else if (tp1 instanceof PrimType && tp2 instanceof PrimType)
209+
if (declType == null)
210+
return possibleRefinement;
211+
else if (possibleRefinement == null)
212+
return declType;
213+
else if (declType == possibleRefinement)
214+
return declType;
215+
else if (TypeUtils.isObjectLikeType(declType))
216+
return possibleRefinement;
217+
else if (TypeUtils.isObjectLikeType(possibleRefinement))
218+
return declType;
219+
else if (declType instanceof PrimType && possibleRefinement instanceof PrimType)
211220
return null;
212-
else if (fastHierarchy.canStoreType(tp2, tp1))
213-
return tp2;
214-
else if (fastHierarchy.canStoreType(tp1, tp2))
215-
return tp1;
221+
else if (fastHierarchy.canStoreType(possibleRefinement, declType))
222+
return possibleRefinement;
223+
else if (fastHierarchy.canStoreType(declType, possibleRefinement))
224+
return declType;
216225
else {
217226
// If one type is an array type and the other one is the base type,
218227
// we still accept the cast
219-
if (tp1 instanceof ArrayType && tp2 instanceof ArrayType) {
220-
ArrayType at1 = (ArrayType) tp1;
221-
ArrayType at2 = (ArrayType) tp2;
228+
if (declType instanceof ArrayType && possibleRefinement instanceof ArrayType) {
229+
ArrayType at1 = (ArrayType) declType;
230+
ArrayType at2 = (ArrayType) possibleRefinement;
222231
if (at1.numDimensions != at2.numDimensions)
223232
return null;
224233
Type preciseType = getMorePreciseType(at1.getElementType(), at2.getElementType());
225234
if (preciseType == null)
226235
return null;
227236

228237
return ArrayType.v(preciseType, at1.numDimensions);
229-
} else if (tp1 instanceof ArrayType) {
230-
ArrayType at = (ArrayType) tp1;
231-
return getMorePreciseType(at.getElementType(), tp2);
232-
} else if (tp2 instanceof ArrayType) {
233-
ArrayType at = (ArrayType) tp2;
234-
return getMorePreciseType(tp1, at.getElementType());
238+
} else if (declType instanceof ArrayType) {
239+
ArrayType at = (ArrayType) declType;
240+
Type preciseType = getMorePreciseType(at.getElementType(), possibleRefinement);
241+
if (preciseType == null)
242+
return null;
243+
244+
return ArrayType.v(preciseType, at.numDimensions);
245+
} else if (possibleRefinement instanceof ArrayType) {
246+
ArrayType at = (ArrayType) possibleRefinement;
247+
return getMorePreciseType(at.getElementType(), declType);
235248
}
236249
}
237250
return null;
238251
}
239252

240-
/**
241-
* Gets the more precise one of the two given types
242-
*
243-
* @param tp1 The first type
244-
* @param tp2 The second type
245-
* @return The more precise one of the two given types
246-
*/
247-
public String getMorePreciseType(String tp1, String tp2) {
248-
Type newType = getMorePreciseType(getTypeFromString(tp1), getTypeFromString(tp2));
249-
return newType == null ? null : "" + newType;
250-
}
251-
252253
/**
253254
* Creates a Soot Type from the given string
254255
*

0 commit comments

Comments
 (0)