Skip to content

Commit d3dd308

Browse files
DIvanov503mrjameshamilton
authored andcommitted
Enable call selection for taint sources and sinks
1 parent 33a0e33 commit d3dd308

30 files changed

+798
-455
lines changed

base/src/main/java/proguard/analysis/cpa/defaults/SetAbstractState.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package proguard.analysis.cpa.defaults;
2020

2121
import java.util.Arrays;
22+
import java.util.Collection;
23+
import java.util.HashMap;
2224
import java.util.HashSet;
2325

2426
/**
@@ -40,7 +42,17 @@ public class SetAbstractState<T>
4042
*/
4143
public SetAbstractState(T... items)
4244
{
43-
addAll(Arrays.asList(items));
45+
this(Arrays.asList(items));
46+
}
47+
48+
/**
49+
* Create a set abstract state from a collection.
50+
*
51+
* @param c a collection of elements
52+
*/
53+
public SetAbstractState(Collection<? extends T> c)
54+
{
55+
super(c);
4456
}
4557

4658
// implementations for LatticeAbstractState

base/src/main/java/proguard/analysis/cpa/domain/taint/TaintAbstractState.java

Lines changed: 0 additions & 73 deletions
This file was deleted.

base/src/main/java/proguard/analysis/cpa/domain/taint/TaintSink.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
package proguard.analysis.cpa.domain.taint;
2020

21+
import proguard.classfile.Signature;
22+
2123
/**
2224
* A {@link TaintSink} specifies a sink for the taint analysis. A sink can be sensitive to
2325
* the instance, the arguments, or the static fields. If a sink S is sensitive to X, then
@@ -27,16 +29,16 @@
2729
*/
2830
public abstract class TaintSink
2931
{
30-
public final String fqn;
32+
public final Signature signature;
3133

3234
/**
3335
* Create a taint sink.
3436
*
35-
* @param fqn the fully qualified name of a sink method
37+
* @param signature the signature of a sink method
3638
*/
37-
public TaintSink(String fqn)
39+
public TaintSink(Signature signature)
3840
{
39-
this.fqn = fqn;
41+
this.signature = signature;
4042
}
4143

4244
@Override

base/src/main/java/proguard/analysis/cpa/domain/taint/TaintSource.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Objects;
2222
import java.util.Set;
2323
import java.util.stream.Collectors;
24+
import proguard.classfile.Signature;
2425

2526
/**
2627
* A {@link TaintSource} specifies a method which can taint any (subset) of the following: the instance, the return value, the argument objects, or static fields.
@@ -30,7 +31,7 @@
3031
public class TaintSource
3132
{
3233

33-
public final String fqn;
34+
public final Signature signature;
3435
public final boolean taintsThis;
3536
public final boolean taintsReturn;
3637
public final Set<Integer> taintsArgs;
@@ -39,15 +40,15 @@ public class TaintSource
3940
/**
4041
* Create a taint source.
4142
*
42-
* @param fqn the fully qualified name of a source method
43+
* @param signature the signature a source method
4344
* @param taintsThis whether the source taints the calling instance
4445
* @param taintsReturn whether the source taints its return
4546
* @param taintsArgs a set of tainted arguments
4647
* @param taintsGlobals a set of tainted global variables
4748
*/
48-
public TaintSource(String fqn, boolean taintsThis, boolean taintsReturn, Set<Integer> taintsArgs, Set<String> taintsGlobals)
49+
public TaintSource(Signature signature, boolean taintsThis, boolean taintsReturn, Set<Integer> taintsArgs, Set<String> taintsGlobals)
4950
{
50-
this.fqn = fqn;
51+
this.signature = signature;
5152
this.taintsThis = taintsThis;
5253
this.taintsReturn = taintsReturn;
5354
this.taintsArgs = taintsArgs;
@@ -68,7 +69,7 @@ public boolean equals(Object obj)
6869
return false;
6970
}
7071
TaintSource other = (TaintSource) obj;
71-
return Objects.equals(fqn, other.fqn)
72+
return Objects.equals(signature, other.signature)
7273
&& taintsThis == other.taintsThis
7374
&& taintsReturn == other.taintsReturn
7475
&& Objects.equals(taintsArgs, other.taintsArgs)
@@ -78,13 +79,13 @@ public boolean equals(Object obj)
7879
@Override
7980
public int hashCode()
8081
{
81-
return Objects.hash(fqn, taintsThis, taintsReturn, taintsArgs, taintsGlobals);
82+
return Objects.hash(signature, taintsThis, taintsReturn, taintsArgs, taintsGlobals);
8283
}
8384

8485
@Override
8586
public String toString()
8687
{
87-
StringBuilder builder = new StringBuilder("[TaintSource] ").append(fqn);
88+
StringBuilder builder = new StringBuilder("[TaintSource] ").append(signature);
8889
if (taintsThis)
8990
{
9091
builder.append(", taints this");

base/src/main/java/proguard/analysis/cpa/jvm/domain/taint/JvmBasicTaintTreeHeapFollowerAbstractState.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import java.util.Map.Entry;
2323
import java.util.stream.Collectors;
2424
import proguard.analysis.cpa.defaults.MapAbstractState;
25-
import proguard.analysis.cpa.domain.taint.TaintAbstractState;
25+
import proguard.analysis.cpa.defaults.SetAbstractState;
2626
import proguard.analysis.cpa.jvm.domain.reference.JvmReferenceAbstractState;
2727
import proguard.analysis.cpa.jvm.domain.reference.Reference;
2828
import proguard.analysis.cpa.jvm.state.heap.JvmHeapAbstractState;
@@ -36,7 +36,7 @@
3636
* @author Dmitry Ivanov
3737
*/
3838
public class JvmBasicTaintTreeHeapFollowerAbstractState
39-
extends JvmTreeHeapFollowerAbstractState<TaintAbstractState>
39+
extends JvmTreeHeapFollowerAbstractState<SetAbstractState<JvmTaintSource>>
4040
implements JvmTaintHeapAbstractState
4141
{
4242

@@ -50,27 +50,27 @@ public class JvmBasicTaintTreeHeapFollowerAbstractState
5050
* @param objectMapAbstractStateFactory a map abstract state factory used for constructing the mapping from fields to values
5151
*/
5252
public JvmBasicTaintTreeHeapFollowerAbstractState(JvmReferenceAbstractState principal,
53-
TaintAbstractState defaultValue, MapAbstractState<Reference, HeapNode<TaintAbstractState>> referenceToNode,
54-
MapAbstractStateFactory<Reference, HeapNode<TaintAbstractState>> heapMapAbstractStateFactory,
55-
MapAbstractStateFactory<String, TaintAbstractState> objectMapAbstractStateFactory)
53+
SetAbstractState<JvmTaintSource> defaultValue, MapAbstractState<Reference, HeapNode<SetAbstractState<JvmTaintSource>>> referenceToNode,
54+
MapAbstractStateFactory<Reference, HeapNode<SetAbstractState<JvmTaintSource>>> heapMapAbstractStateFactory,
55+
MapAbstractStateFactory<String, SetAbstractState<JvmTaintSource>> objectMapAbstractStateFactory)
5656
{
5757
super(principal, defaultValue, referenceToNode, heapMapAbstractStateFactory, objectMapAbstractStateFactory);
5858
}
5959

6060
// implementations for JvmTaintHeapAbstractState
6161

6262
@Override
63-
public <T> void taintObject(T object, TaintAbstractState value)
63+
public <T> void taintObject(T object, SetAbstractState<JvmTaintSource> value)
6464
{
6565
}
6666

6767
// implementations for LatticeAbstractState
6868

6969
@Override
70-
public JvmBasicTaintTreeHeapFollowerAbstractState join(JvmHeapAbstractState<TaintAbstractState> abstractState)
70+
public JvmBasicTaintTreeHeapFollowerAbstractState join(JvmHeapAbstractState<SetAbstractState<JvmTaintSource>> abstractState)
7171
{
7272
JvmBasicTaintTreeHeapFollowerAbstractState other = (JvmBasicTaintTreeHeapFollowerAbstractState) abstractState;
73-
MapAbstractState<Reference, HeapNode<TaintAbstractState>> newReferenceToNode = referenceToNode.join(other.referenceToNode);
73+
MapAbstractState<Reference, HeapNode<SetAbstractState<JvmTaintSource>>> newReferenceToNode = referenceToNode.join(other.referenceToNode);
7474
if (referenceToNode == newReferenceToNode)
7575
{
7676
return this;

base/src/main/java/proguard/analysis/cpa/jvm/domain/taint/JvmInvokeTaintSink.java

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@
2020

2121
import java.util.HashSet;
2222
import java.util.Objects;
23+
import java.util.Optional;
2324
import java.util.Set;
25+
import java.util.function.Predicate;
2426
import java.util.stream.Collectors;
2527
import proguard.analysis.cpa.interfaces.CallEdge;
2628
import proguard.analysis.cpa.jvm.cfa.edges.JvmCallCfaEdge;
2729
import proguard.analysis.cpa.jvm.cfa.edges.JvmCfaEdge;
2830
import proguard.analysis.cpa.jvm.witness.JvmMemoryLocation;
2931
import proguard.analysis.cpa.jvm.witness.JvmStackLocation;
3032
import proguard.analysis.cpa.jvm.witness.JvmStaticFieldLocation;
33+
import proguard.analysis.datastructure.callgraph.Call;
34+
import proguard.classfile.Signature;
3135
import proguard.classfile.util.ClassUtil;
3236

3337
/**
@@ -41,27 +45,58 @@ public class JvmInvokeTaintSink
4145
extends JvmTaintSink
4246
{
4347

48+
public final Optional<Predicate<Call>> callMatcher;
49+
4450
public final boolean takesInstance;
4551
public final Set<Integer> takesArgs;
4652
public final Set<String> takesGlobals;
4753

4854
/**
4955
* Create a taint sink.
5056
*
51-
* @param fqn the fully qualified name of a sink method
57+
* @param signature the signature of a sink method
58+
* @param takesInstance whether the sink is sensitive to the calling instance
59+
* @param takesArgs a set of sensitive arguments
60+
* @param takesGlobals a set of sensitive global variables
61+
*/
62+
public JvmInvokeTaintSink(Signature signature, boolean takesInstance, Set<Integer> takesArgs, Set<String> takesGlobals)
63+
{
64+
this(signature, Optional.empty(), takesInstance, takesArgs, takesGlobals);
65+
}
66+
67+
/**
68+
* Create a taint sink.
69+
*
70+
* @param signature the signature of a sink method
71+
* @param callMatcher whether the call matches this taint sink
72+
* @param takesInstance whether the sink is sensitive to the calling instance
73+
* @param takesArgs a set of sensitive arguments
74+
* @param takesGlobals a set of sensitive global variables
75+
*/
76+
public JvmInvokeTaintSink(Signature signature, Predicate<Call> callMatcher, boolean takesInstance, Set<Integer> takesArgs, Set<String> takesGlobals)
77+
{
78+
this(signature, Optional.of(callMatcher), takesInstance, takesArgs, takesGlobals);
79+
}
80+
81+
/**
82+
* Create a taint sink.
83+
*
84+
* @param signature the signature of a sink method
85+
* @param callMatcher an optional predicate on whether the call matches this taint sink
5286
* @param takesInstance whether the sink is sensitive to the calling instance
5387
* @param takesArgs a set of sensitive arguments
5488
* @param takesGlobals a set of sensitive global variables
5589
*/
56-
public JvmInvokeTaintSink(String fqn, boolean takesInstance, Set<Integer> takesArgs, Set<String> takesGlobals)
90+
private JvmInvokeTaintSink(Signature signature, Optional<Predicate<Call>> callMatcher, boolean takesInstance, Set<Integer> takesArgs, Set<String> takesGlobals)
5791
{
58-
super(fqn);
92+
super(signature);
5993

6094
if (!takesInstance && takesArgs.isEmpty() && takesGlobals.isEmpty())
6195
{
62-
throw new RuntimeException(String.format("Tainted sink for method %s must have taint somewhere!", fqn));
96+
throw new RuntimeException(String.format("Tainted sink for method %s must have taint somewhere!", signature));
6397
}
6498

99+
this.callMatcher = callMatcher;
65100
this.takesInstance = takesInstance;
66101
this.takesArgs = takesArgs;
67102
this.takesGlobals = takesGlobals;
@@ -74,14 +109,15 @@ public JvmInvokeTaintSink(String fqn, boolean takesInstance, Set<Integer> takesA
74109
public Set<JvmMemoryLocation> getMemoryLocations()
75110
{
76111
Set<JvmMemoryLocation> result = new HashSet<>();
112+
String fqn = signature.getFqn();
77113
String descriptor = fqn.substring(fqn.indexOf("("));
78114
int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
79115
if (takesInstance)
80116
{
81117
result.add(new JvmStackLocation(parameterSize));
82118
}
83119
takesArgs.forEach(i -> result.add(new JvmStackLocation(parameterSize - ClassUtil.internalMethodVariableIndex(descriptor, true, i))));
84-
takesGlobals.forEach(fqn -> result.add(new JvmStaticFieldLocation(fqn)));
120+
takesGlobals.forEach(n -> result.add(new JvmStaticFieldLocation(n)));
85121
return result;
86122
}
87123

@@ -91,7 +127,12 @@ public Set<JvmMemoryLocation> getMemoryLocations()
91127
@Override
92128
public boolean matchCfaEdge(JvmCfaEdge edge)
93129
{
94-
return edge instanceof JvmCallCfaEdge && fqn.equals(((CallEdge) edge).getCall().getTarget().getFqn());
130+
if (!(edge instanceof JvmCallCfaEdge))
131+
{
132+
return false;
133+
}
134+
CallEdge callEdge = (CallEdge) edge;
135+
return signature.equals(callEdge.getCall().getTarget()) && callMatcher.map(p -> p.test(callEdge.getCall())).orElse(true);
95136
}
96137

97138
@Override
@@ -107,21 +148,22 @@ public boolean equals(Object o)
107148
}
108149
JvmInvokeTaintSink taintSink = (JvmInvokeTaintSink) o;
109150
return takesInstance == taintSink.takesInstance
110-
&& Objects.equals(fqn, taintSink.fqn)
151+
&& Objects.equals(signature, taintSink.signature)
111152
&& Objects.equals(takesArgs, taintSink.takesArgs)
112-
&& Objects.equals(takesGlobals, taintSink.takesGlobals);
153+
&& Objects.equals(takesGlobals, taintSink.takesGlobals)
154+
&& Objects.equals(callMatcher, taintSink.callMatcher);
113155
}
114156

115157
@Override
116158
public int hashCode()
117159
{
118-
return Objects.hash(fqn, takesInstance, takesArgs, takesGlobals);
160+
return Objects.hash(signature, takesInstance, takesArgs, takesGlobals, callMatcher);
119161
}
120162

121163
@Override
122164
public String toString()
123165
{
124-
StringBuilder result = new StringBuilder("[JvmInvokeTaintSink] ").append(fqn);
166+
StringBuilder result = new StringBuilder("[JvmInvokeTaintSink] ").append(signature);
125167
if (takesInstance)
126168
{
127169
result.append(", takes instance");
@@ -143,6 +185,7 @@ public String toString()
143185
.collect(Collectors.joining(", ")))
144186
.append(")");
145187
}
188+
callMatcher.ifPresent(p -> result.append(" filtered by ").append(p));
146189

147190
return result.toString();
148191
}

0 commit comments

Comments
 (0)