Skip to content

Commit bf001fc

Browse files
committed
Refactor
1 parent 4031a8a commit bf001fc

File tree

1 file changed

+41
-63
lines changed

1 file changed

+41
-63
lines changed

java/ql/lib/semmle/code/java/dataflow/ListOfConstantsSanitizer.qll

Lines changed: 41 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ module Collection {
8888
}
8989
}
9090

91-
/** A call where a collection of constants of class `collectionClass` can be in */
91+
/**
92+
* A call with a collection of class `collectionClass` as argument `arg` (or
93+
* as qualifier, if `arg` is -1) which will not add any new non-constant
94+
* elements to it.
95+
*/
9296
abstract class SafeCall extends Call {
9397
int arg;
9498
CollectionClass collectionClass;
@@ -120,7 +124,7 @@ module Collection {
120124
or
121125
collectionClass = "Set" and
122126
t.hasQualifiedName("java.util", "Set") and
123-
m.getName() = ["add"] and
127+
m.getName() = "add" and
124128
this.getArgument(0).isCompileTimeConstant()
125129
)
126130
}
@@ -140,40 +144,19 @@ module Collection {
140144
}
141145
}
142146

143-
// Expr foo(Expr q, string s) {
144-
// q = any(CollectionContainsCall ccc).getQualifier() and
145-
// result = getALocalExprFlowRoot(q) and
146-
// (
147-
// if exists(Field f | DataFlow::localExprFlow(f.getAnAccess(), result))
148-
// then
149-
// exists(Field f | DataFlow::localExprFlow(f.getAnAccess(), result) |
150-
// f.isStatic() and
151-
// f.isFinal() and
152-
// s = "static final field"
153-
// or
154-
// not (
155-
// f.isStatic() and
156-
// f.isFinal()
157-
// ) and
158-
// s = "field read"
159-
// )
160-
// else
161-
// if result = any(MethodCall mc)
162-
// then s = "method call"
163-
// else
164-
// if result = any(ConstructorCall cc)
165-
// then s = "constructor call"
166-
// else
167-
// if result = any(Call cc)
168-
// then s = "other call"
169-
// else s = "something else"
170-
// )
171-
// }
172-
Expr getALocalExprFlowRoot(Expr e) {
147+
/**
148+
* Gets an `Expr` which locally flows to `e` and which nothing locally flows
149+
* to.
150+
*/
151+
private Expr getALocalExprFlowRoot(Expr e) {
173152
DataFlow::localExprFlow(result, e) and
174153
not exists(Expr e2 | e2 != result | DataFlow::localExprFlow(e2, result))
175154
}
176155

156+
/**
157+
* Holds if `e` was not involved in any calls which might add non-constant
158+
* elements.
159+
*/
177160
private predicate noUnsafeCalls(Expr e) {
178161
forall(MethodCall mc, int arg, Expr x |
179162
DataFlow::localExprFlow(x, e) and
@@ -187,20 +170,19 @@ module Collection {
187170
)
188171
}
189172

190-
private predicate collectionOfConstantsFlowsTo(Expr e) {
173+
/** Holds if `e` is a collection of constants. */
174+
private predicate isCollectionOfConstants(Expr e) {
191175
forex(Expr r | r = getALocalExprFlowRoot(e) |
192176
r instanceof CollectionOfConstants
193177
or
194178
// Access a static final field to get an immutable list of constants.
195179
exists(Field f | r = f.getAnAccess() |
196180
f.isStatic() and
197181
f.isFinal() and
198-
forall(Expr v | v = f.getInitializer() |
199-
v = any(CollectionOfConstants loc | loc.isImmutable())
200-
) and
182+
forall(Expr v | v = f.getInitializer() | v instanceof ImmutableCollectionOfConstants) and
201183
forall(Expr fieldSource | fieldSource = f.getAnAccess().(FieldWrite).getASource() |
202184
forall(Expr root | root = getALocalExprFlowRoot(fieldSource) |
203-
root.(CollectionOfConstants).isImmutable()
185+
root instanceof ImmutableCollectionOfConstants
204186
) and
205187
noUnsafeCalls(fieldSource)
206188
)
@@ -210,36 +192,40 @@ module Collection {
210192
}
211193

212194
/**
213-
* An invocation of `java.util.List.contains` where the qualifier contains only
214-
* compile-time constants.
195+
* An invocation of `java.util.List.contains` or `java.util.Set.contains`
196+
* where the qualifier contains only compile-time constants.
215197
*/
216198
private class CollectionOfConstantsContains extends ListOfConstantsComparison {
217199
CollectionOfConstantsContains() {
218200
exists(CollectionContainsCall mc |
219201
this = mc and
220202
e = mc.getArgument(0) and
221203
outcome = true and
222-
collectionOfConstantsFlowsTo(mc.getQualifier())
204+
isCollectionOfConstants(mc.getQualifier())
223205
)
224206
}
225207
}
226208

227209
/**
228-
* An instance of `java.util.List` which contains only compile-time constants.
210+
* An instance of `java.util.List` or `java.util.Set` which contains only
211+
* compile-time constants.
229212
*/
230213
abstract class CollectionOfConstants extends Call {
231214
CollectionClass collectionClass;
232215

233216
/** Gets whether the collection is a "List" or a "Set". */
234217
CollectionClass getCollectionClass() { result = collectionClass }
235-
236-
/** Holds if this list of constants is immutable. */
237-
abstract predicate isImmutable();
238218
}
239219

220+
/**
221+
* An immutable instance of `java.util.List` or `java.util.Set` which
222+
* contains only compile-time constants.
223+
*/
224+
abstract class ImmutableCollectionOfConstants extends CollectionOfConstants { }
225+
240226
/**
241227
* A invocation of a constructor of a type that extends `java.util.List` or
242-
* `java.util.Set` which constructs an empty mutable list.
228+
* `java.util.Set` which constructs an empty mutable list/set.
243229
*/
244230
private class CollectionOfConstantsEmptyConstructor extends ClassInstanceExpr,
245231
CollectionOfConstants
@@ -260,13 +246,11 @@ module Collection {
260246
c.getParameter(0).getType().(PrimitiveType).hasName("float")
261247
)
262248
}
263-
264-
override predicate isImmutable() { none() }
265249
}
266250

267251
/**
268252
* A invocation of a constructor of a type that extends `java.util.List` or
269-
* `java.util.Set` which constructs a non-empty mutable list.
253+
* `java.util.Set` which constructs a non-empty mutable list/set.
270254
*/
271255
private class CollectionOfConstantsNonEmptyConstructor extends ClassInstanceExpr,
272256
CollectionOfConstants
@@ -284,11 +268,9 @@ module Collection {
284268
.getASourceSupertype*()
285269
.hasQualifiedName("java.util", "Collection")
286270
) and
287-
// Any collection can be used in the non-empty constructor.
288-
collectionOfConstantsFlowsTo(this.getArgument(0))
271+
// Note that any collection can be used in the non-empty constructor.
272+
isCollectionOfConstants(this.getArgument(0))
289273
}
290-
291-
override predicate isImmutable() { none() }
292274
}
293275

294276
/**
@@ -306,15 +288,15 @@ module Collection {
306288
) and
307289
methodCallHasConstantArguments(this)
308290
}
309-
310-
override predicate isImmutable() { none() }
311291
}
312292

313293
/**
314-
* An invocation of `java.util.List.of` which constructs an immutable list
315-
* which contains only compile-time constants.
294+
* An invocation of `java.util.List.of` or `java.util.Set.of` which
295+
* constructs an immutable list/set which contains only compile-time constants.
316296
*/
317-
private class CollectionOfConstantsCreatedWithOf extends MethodCall, CollectionOfConstants {
297+
private class CollectionOfConstantsCreatedWithOf extends MethodCall,
298+
ImmutableCollectionOfConstants
299+
{
318300
CollectionOfConstantsCreatedWithOf() {
319301
exists(Method m | this.getMethod() = m |
320302
m.hasName("of") and
@@ -325,8 +307,6 @@ module Collection {
325307
) and
326308
methodCallHasConstantArguments(this)
327309
}
328-
329-
override predicate isImmutable() { any() }
330310
}
331311

332312
/**
@@ -335,7 +315,7 @@ module Collection {
335315
* list/set which contains only compile-time constants.
336316
*/
337317
private class CollectionOfConstantsCreatedWithCollectionsUnmodifiableList extends MethodCall,
338-
CollectionOfConstants
318+
ImmutableCollectionOfConstants
339319
{
340320
CollectionOfConstantsCreatedWithCollectionsUnmodifiableList() {
341321
exists(Method m |
@@ -346,10 +326,8 @@ module Collection {
346326
.hasQualifiedName("java.util", "Collections") and
347327
this.getMethod() = m
348328
|
349-
collectionOfConstantsFlowsTo(this.getArgument(0))
329+
isCollectionOfConstants(this.getArgument(0))
350330
)
351331
}
352-
353-
override predicate isImmutable() { any() }
354332
}
355333
}

0 commit comments

Comments
 (0)