@@ -159,6 +159,41 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) {
159
159
method .( CollectionMethod ) .hasName ( "offer" ) and arg = 0
160
160
}
161
161
162
+ /**
163
+ * Holds if `method` is a library method that returns tainted data if its
164
+ * `arg`th argument is tainted.
165
+ */
166
+ private predicate taintPreservingArgumentToMethod ( Method method , int arg ) {
167
+ method .getDeclaringType ( ) .hasQualifiedName ( "java.util" , "Collections" ) and
168
+ (
169
+ method
170
+ .hasName ( [ "singleton" , "singletonList" , "singletonMap" , "enumeration" , "list" , "max" , "min" ,
171
+ "asLifoQueue" , "checkedCollection" , "checkedList" , "checkedMap" , "checkedSet" ,
172
+ "checkedSortedMap" , "checkedSortedSet" , "synchronizedCollection" , "synchronizedList" ,
173
+ "synchronizedMap" , "synchronizedSet" , "synchronizedSortedMap" ,
174
+ "synchronizedSortedSet" , "unmodifiableCollection" , "unmodifiableList" ,
175
+ "unmodifiableMap" , "unmodifiableSet" , "unmodifiableSortedMap" , "unmodifiableSortedSet" ] ) and
176
+ arg = 0
177
+ or
178
+ method .hasName ( [ "nCopies" , "singletonMap" ] ) and arg = 1
179
+ )
180
+ }
181
+
182
+ /**
183
+ * Holds if `method` is a library method that writes tainted data to the
184
+ * `output`th argument if the `input`th argument is tainted.
185
+ */
186
+ private predicate taintPreservingArgToArg ( Method method , int input , int output ) {
187
+ method .getDeclaringType ( ) .hasQualifiedName ( "java.util" , "Collections" ) and
188
+ (
189
+ method .hasName ( [ "copy" , "fill" ] ) and
190
+ input = 1 and
191
+ output = 0
192
+ or
193
+ method .hasName ( "replaceAll" ) and input = 2 and output = 0
194
+ )
195
+ }
196
+
162
197
private predicate argToQualifierStep ( Expr tracked , Expr sink ) {
163
198
exists ( Method m , int i , MethodAccess ma |
164
199
taintPreservingArgumentToQualifier ( m , i ) and
@@ -168,13 +203,37 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) {
168
203
)
169
204
}
170
205
206
+ /** Access to a method that passes taint from an argument. */
207
+ private predicate argToMethodStep ( Expr tracked , MethodAccess sink ) {
208
+ exists ( Method m , int i |
209
+ m = sink .( MethodAccess ) .getMethod ( ) and
210
+ taintPreservingArgumentToMethod ( m , i ) and
211
+ tracked = sink .( MethodAccess ) .getArgument ( i )
212
+ )
213
+ }
214
+
215
+ /**
216
+ * Holds if `tracked` and `sink` are arguments to a method that transfers taint
217
+ * between arguments.
218
+ */
219
+ private predicate argToArgStep ( Expr tracked , Expr sink ) {
220
+ exists ( MethodAccess ma , Method method , int input , int output |
221
+ taintPreservingArgToArg ( method , input , output ) and
222
+ ma .getMethod ( ) = method and
223
+ ma .getArgument ( input ) = tracked and
224
+ ma .getArgument ( output ) = sink
225
+ )
226
+ }
227
+
171
228
/**
172
229
* Holds if the step from `n1` to `n2` is either extracting a value from a
173
230
* container, inserting a value into a container, or transforming one container
174
231
* to another. This is restricted to cases where `n2` is the returned value of
175
232
* a call.
176
233
*/
177
- predicate containerReturnValueStep ( Expr n1 , Expr n2 ) { qualifierToMethodStep ( n1 , n2 ) }
234
+ predicate containerReturnValueStep ( Expr n1 , Expr n2 ) {
235
+ qualifierToMethodStep ( n1 , n2 ) or argToMethodStep ( n1 , n2 )
236
+ }
178
237
179
238
/**
180
239
* Holds if the step from `n1` to `n2` is either extracting a value from a
@@ -183,7 +242,8 @@ predicate containerReturnValueStep(Expr n1, Expr n2) { qualifierToMethodStep(n1,
183
242
*/
184
243
predicate containerUpdateStep ( Expr n1 , Expr n2 ) {
185
244
qualifierToArgumentStep ( n1 , n2 ) or
186
- argToQualifierStep ( n1 , n2 )
245
+ argToQualifierStep ( n1 , n2 ) or
246
+ argToArgStep ( n1 , n2 )
187
247
}
188
248
189
249
/**
0 commit comments