Skip to content

Commit a1d272e

Browse files
authored
Merge pull request github#3918 from aibaars/organise-container-flow
Java: Clean up ContainerFlow, consider more methods
2 parents 05685cc + 43b6103 commit a1d272e

File tree

4 files changed

+501
-26
lines changed

4 files changed

+501
-26
lines changed

java/ql/src/semmle/code/java/dataflow/internal/ContainerFlow.qll

Lines changed: 133 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -89,81 +89,189 @@ class ContainerType extends RefType {
8989
}
9090

9191
private predicate taintPreservingQualifierToMethod(Method m) {
92+
// java.util.Map.Entry
9293
m.getDeclaringType() instanceof EntryType and
93-
m.hasName("getValue")
94+
m.hasName(["getValue", "setValue"])
9495
or
96+
// java.util.Iterable
9597
m.getDeclaringType() instanceof IterableType and
96-
m.hasName("iterator")
98+
m.hasName(["iterator", "spliterator"])
9799
or
100+
// java.util.Iterator
98101
m.getDeclaringType() instanceof IteratorType and
99102
m.hasName("next")
100103
or
104+
// java.util.ListIterator
105+
m.getDeclaringType() instanceof IteratorType and
106+
m.hasName("previous")
107+
or
108+
// java.util.Enumeration
101109
m.getDeclaringType() instanceof EnumerationType and
102-
m.hasName("nextElement")
110+
m.hasName(["asIterator", "nextElement"])
103111
or
104-
m.(MapMethod).hasName("entrySet")
112+
// java.util.Map
113+
m
114+
.(MapMethod)
115+
.hasName(["computeIfAbsent", "entrySet", "get", "getOrDefault", "put", "putIfAbsent",
116+
"remove", "replace", "values"])
105117
or
106-
m.(MapMethod).hasName("get")
118+
// java.util.Collection
119+
m.(CollectionMethod).hasName(["parallelStream", "stream", "toArray"])
107120
or
108-
m.(MapMethod).hasName("remove")
121+
// java.util.List
122+
m.(CollectionMethod).hasName(["get", "listIterator", "set", "subList"])
109123
or
110-
m.(MapMethod).hasName("values")
124+
m.(CollectionMethod).hasName("remove") and m.getParameterType(0).(PrimitiveType).hasName("int")
111125
or
112-
m.(CollectionMethod).hasName("toArray")
126+
// java.util.Vector
127+
m.(CollectionMethod).hasName(["elementAt", "elements", "firstElement", "lastElement"])
113128
or
114-
m.(CollectionMethod).hasName("get")
129+
// java.util.Stack
130+
m.(CollectionMethod).hasName(["peek", "pop"])
115131
or
116-
m.(CollectionMethod).hasName("remove") and m.getParameterType(0).(PrimitiveType).hasName("int")
132+
// java.util.Queue
133+
m.(CollectionMethod).hasName(["element", "poll"])
117134
or
118135
m.(CollectionMethod).hasName("remove") and m.getNumberOfParameters() = 0
119136
or
120-
m.(CollectionMethod).hasName("subList")
137+
// java.util.Deque
138+
m
139+
.(CollectionMethod)
140+
.hasName(["getFirst", "getLast", "peekFirst", "peekLast", "pollFirst", "pollLast",
141+
"removeFirst", "removeLast"])
142+
or
143+
// java.util.concurrent.BlockingQueue
144+
// covered by Queue: poll(long, TimeUnit)
145+
m.(CollectionMethod).hasName("take")
146+
or
147+
// java.util.concurrent.BlockingDeque
148+
// covered by Deque: pollFirst(long, TimeUnit), pollLast(long, TimeUnit)
149+
m.(CollectionMethod).hasName(["takeFirst", "takeLast"])
150+
or
151+
// java.util.SortedSet
152+
m.(CollectionMethod).hasName(["first", "headSet", "last", "subSet", "tailSet"])
121153
or
122-
m.(CollectionMethod).hasName("firstElement")
154+
// java.util.NavigableSet
155+
// covered by Deque: pollFirst(), pollLast()
156+
// covered by SortedSet: headSet(E, boolean), subSet(E, boolean, E, boolean) and tailSet(E, boolean)
157+
m
158+
.(CollectionMethod)
159+
.hasName(["ceiling", "descendingIterator", "descendingSet", "floor", "higher", "lower"])
123160
or
124-
m.(CollectionMethod).hasName("lastElement")
161+
// java.util.SortedMap
162+
m.(MapMethod).hasName(["headMap", "subMap", "tailMap"])
125163
or
126-
m.(CollectionMethod).hasName("poll")
164+
// java.util.NavigableMap
165+
// covered by SortedMap: headMap(K, boolean), subMap(K, boolean, K, boolean), tailMap(K, boolean)
166+
m
167+
.(MapMethod)
168+
.hasName(["ceilingEntry", "descendingMap", "firstEntry", "floorEntry", "higherEntry",
169+
"lastEntry", "lowerEntry", "pollFirstEntry", "pollLastEntry"])
127170
or
128-
m.(CollectionMethod).hasName("peek")
171+
// java.util.Dictionary
172+
m
173+
.getDeclaringType()
174+
.getSourceDeclaration()
175+
.getASourceSupertype*()
176+
.hasQualifiedName("java.util", "Dictionary") and
177+
m.hasName(["elements", "get", "put", "remove"])
129178
or
130-
m.(CollectionMethod).hasName("element")
179+
// java.util.concurrent.ConcurrentHashMap
180+
m.(MapMethod).hasName(["elements", "search", "searchEntries", "searchValues"])
131181
}
132182

133183
private predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
134184
taintPreservingQualifierToMethod(sink.getMethod()) and
135185
tracked = sink.getQualifier()
136186
}
137187

138-
private predicate qualifierToArgumentStep(Expr tracked, RValue sink) {
139-
exists(MethodAccess ma |
140-
ma.getMethod().(CollectionMethod).hasName("toArray") and
188+
private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
189+
exists(MethodAccess ma, CollectionMethod method |
190+
method = ma.getMethod() and
191+
(
192+
// java.util.Vector
193+
method.hasName("copyInto")
194+
or
195+
// java.util.concurrent.BlockingQueue
196+
method.hasName("drainTo")
197+
or
198+
// java.util.Collection
199+
method.hasName("toArray") and method.getParameter(0).getType() instanceof Array
200+
) and
141201
tracked = ma.getQualifier() and
142-
sink = ma.getArgument(1)
202+
sink = ma.getArgument(0)
143203
)
144204
}
145205

146206
private predicate taintPreservingArgumentToQualifier(Method method, int arg) {
147-
method.(MapMethod).hasName("put") and arg = 1
207+
// java.util.Map.Entry
208+
method.getDeclaringType() instanceof EntryType and
209+
method.hasName("setValue") and
210+
arg = 0
148211
or
149-
method.(MapMethod).hasName("putAll") and arg = 0
212+
// java.util.Map
213+
method.(MapMethod).hasName(["merge", "put", "putIfAbsent"]) and arg = 1
150214
or
151-
method.(CollectionMethod).hasName("add") and arg = method.getNumberOfParameters() - 1
215+
method.(MapMethod).hasName("replace") and arg = method.getNumberOfParameters() - 1
152216
or
153-
method.(CollectionMethod).hasName("addAll") and arg = method.getNumberOfParameters() - 1
217+
method.(MapMethod).hasName("putAll") and arg = 0
218+
or
219+
// java.util.ListIterator
220+
method.getDeclaringType() instanceof IteratorType and
221+
method.hasName(["add", "set"]) and
222+
arg = 0
154223
or
155-
method.(CollectionMethod).hasName("addElement") and arg = 0
224+
// java.util.Collection
225+
method.(CollectionMethod).hasName(["add", "addAll"]) and
226+
// Refer to the last parameter to also cover List::add(int, E) and List::addAll(int, Collection)
227+
arg = method.getNumberOfParameters() - 1
156228
or
229+
// java.util.List
230+
// covered by Collection: add(int, E), addAll(int, Collection<? extends E>)
157231
method.(CollectionMethod).hasName("set") and arg = 1
158232
or
233+
// java.util.Vector
234+
method.(CollectionMethod).hasName(["addElement", "insertElementAt", "setElementAt"]) and arg = 0
235+
or
236+
// java.util.Stack
237+
method.(CollectionMethod).hasName("push") and arg = 0
238+
or
239+
// java.util.Queue
159240
method.(CollectionMethod).hasName("offer") and arg = 0
241+
or
242+
// java.util.Deque
243+
// covered by Stack: push(E)
244+
method.(CollectionMethod).hasName(["addFirst", "addLast", "offerFirst", "offerLast"]) and arg = 0
245+
or
246+
// java.util.concurrent.BlockingQueue
247+
// covered by Queue: offer(E, long, TimeUnit)
248+
method.(CollectionMethod).hasName("put") and arg = 0
249+
or
250+
// java.util.concurrent.TransferQueue
251+
method.(CollectionMethod).hasName(["transfer", "tryTransfer"]) and arg = 0
252+
or
253+
// java.util.concurrent.BlockingDeque
254+
// covered by Deque: offerFirst(E, long, TimeUnit), offerLast(E, long, TimeUnit)
255+
method.(CollectionMethod).hasName(["putFirst", "putLast"]) and arg = 0
256+
or
257+
//java.util.Dictionary
258+
method
259+
.getDeclaringType()
260+
.getSourceDeclaration()
261+
.getASourceSupertype*()
262+
.hasQualifiedName("java.util", "Dictionary") and
263+
method.hasName("put") and
264+
arg = 1
160265
}
161266

162267
/**
163268
* Holds if `method` is a library method that returns tainted data if its
164269
* `arg`th argument is tainted.
165270
*/
166271
private predicate taintPreservingArgumentToMethod(Method method, int arg) {
272+
// java.util.Stack
273+
method.(CollectionMethod).hasName("push") and arg = 0
274+
or
167275
method.getDeclaringType().hasQualifiedName("java.util", "Collections") and
168276
(
169277
method

0 commit comments

Comments
 (0)