@@ -63,53 +63,82 @@ predicate methodCallHasConstantArguments(MethodCall mc) {
6363 )
6464}
6565
66- /** Classes for `java.util.List`. */
67- module JavaUtilList {
68- private class JavaUtilListContainsCall extends MethodCall {
69- JavaUtilListContainsCall ( ) {
66+ class CollectionClass extends string {
67+ CollectionClass ( ) { this = [ "List" , "Set" ] }
68+ }
69+
70+ /** Classes for `java.util.List` and `java.util.Set`. */
71+ module Collection {
72+ private class CollectionContainsCall extends MethodCall {
73+ CollectionClass collectionClass ;
74+
75+ /** Gets whether the collection is a "List" or a "Set". */
76+ CollectionClass getCollectionClass ( ) { result = collectionClass }
77+
78+ CollectionContainsCall ( ) {
7079 exists ( Method m |
7180 this .getMethod ( ) = m and
7281 m .hasName ( "contains" ) and
73- m .getDeclaringType ( ) .getSourceDeclaration ( ) .hasQualifiedName ( "java.util" , "List" )
82+ m .getDeclaringType ( )
83+ .getSourceDeclaration ( )
84+ .getASourceSupertype * ( )
85+ .hasQualifiedName ( "java.util" , collectionClass )
7486 )
7587 }
7688 }
7789
7890 private class NonConstantElementAddition extends Expr {
91+ CollectionClass collectionClass ;
92+
93+ /** Gets whether the collection is a "List" or a "Set". */
94+ CollectionClass getCollectionClass ( ) { result = collectionClass }
95+
7996 NonConstantElementAddition ( ) {
8097 exists ( Method m , RefType t , MethodCall mc |
8198 this = mc .getQualifier ( ) and
8299 mc .getMethod ( ) = m and
83100 t = m .getDeclaringType ( ) .getSourceDeclaration ( ) .getASourceSupertype * ( )
84101 |
102+ collectionClass = "List" and
85103 t .hasQualifiedName ( "java.util" , "List" ) and
86104 m .getName ( ) = [ "add" , "addFirst" , "addLast" ] and
87105 not mc .getArgument ( m .getNumberOfParameters ( ) - 1 ) .isCompileTimeConstant ( )
88106 or
107+ collectionClass = "Set" and
108+ t .hasQualifiedName ( "java.util" , "Set" ) and
109+ m .getName ( ) = [ "add" ] and
110+ not mc .getArgument ( 0 ) .isCompileTimeConstant ( )
111+ or
89112 // If a whole collection is added then we don't try to track if it contains
90113 // only compile-time constants, and conservatively assume that it does.
91- t .hasQualifiedName ( "java.util" , [ "Collection" , "List" ] ) and m .getName ( ) = "addAll"
114+ t .hasQualifiedName ( "java.util" , "Collection" ) and
115+ m .getName ( ) = "addAll"
92116 )
93117 }
94118 }
95119
96- private predicate javaUtilListOfConstantsLocalFlowTo ( Expr e ) {
97- exists ( JavaUtilListOfConstants loc | DataFlow:: localExprFlow ( loc , e ) |
120+ private predicate collectionOfConstantsLocalFlowTo ( CollectionClass collectionClass , Expr e ) {
121+ exists ( CollectionOfConstants loc |
122+ loc .getCollectionClass ( ) = collectionClass and DataFlow:: localExprFlow ( loc , e )
123+ |
98124 loc .isImmutable ( )
99125 or
100126 not DataFlow:: localExprFlow ( any ( NonConstantElementAddition ncea ) , e )
101127 )
102128 }
103129
104- private predicate javaUtilListOfConstantsFlowsTo ( Expr e ) {
105- javaUtilListOfConstantsLocalFlowTo ( e )
130+ private predicate collectionOfConstantsFlowsTo ( CollectionClass collectionClass , Expr e ) {
131+ collectionOfConstantsLocalFlowTo ( collectionClass , e )
106132 or
107133 // Access a static final field to get an immutable list of constants.
108134 exists ( Field f |
109135 f .isStatic ( ) and
110136 f .isFinal ( ) and
111137 forall ( Expr v | v = f .getInitializer ( ) or v = f .getAnAccess ( ) .( FieldWrite ) .getASource ( ) |
112- v = any ( JavaUtilListOfConstants loc | loc .isImmutable ( ) )
138+ v =
139+ any ( CollectionOfConstants loc |
140+ loc .getCollectionClass ( ) = collectionClass and loc .isImmutable ( )
141+ )
113142 )
114143 |
115144 DataFlow:: localExprFlow ( f .getAnAccess ( ) , e )
@@ -120,60 +149,69 @@ module JavaUtilList {
120149 * An invocation of `java.util.List.contains` where the qualifier contains only
121150 * compile-time constants.
122151 */
123- private class JavaUtilListOfConstantsContains extends ListOfConstantsComparison {
124- JavaUtilListOfConstantsContains ( ) {
125- exists ( JavaUtilListContainsCall mc |
152+ private class CollectionOfConstantsContains extends ListOfConstantsComparison {
153+ CollectionOfConstantsContains ( ) {
154+ exists ( CollectionContainsCall mc |
126155 this = mc and
127156 e = mc .getArgument ( 0 ) and
128157 outcome = true and
129- javaUtilListOfConstantsFlowsTo ( mc .getQualifier ( ) )
158+ collectionOfConstantsFlowsTo ( mc . getCollectionClass ( ) , mc .getQualifier ( ) )
130159 )
131160 }
132161 }
133162
134163 /**
135164 * An instance of `java.util.List` which contains only compile-time constants.
136165 */
137- abstract class JavaUtilListOfConstants extends Call {
166+ abstract class CollectionOfConstants extends Call {
167+ CollectionClass collectionClass ;
168+
169+ /** Gets whether the collection is a "List" or a "Set". */
170+ CollectionClass getCollectionClass ( ) { result = collectionClass }
171+
138172 /** Holds if this list of constants is immutable. */
139173 abstract predicate isImmutable ( ) ;
140174 }
141175
142176 /**
143- * A invocation of a constructor of a type that extends `java.util.List`
144- * which constructs an empty mutable list.
177+ * A invocation of a constructor of a type that extends `java.util.List` or
178+ * `java.util.Set` which constructs an empty mutable list.
145179 */
146- private class JavaUtilListOfConstantsEmptyConstructor extends ClassInstanceExpr ,
147- JavaUtilListOfConstants
180+ private class CollectionOfConstantsEmptyConstructor extends ClassInstanceExpr ,
181+ CollectionOfConstants
148182 {
149- JavaUtilListOfConstantsEmptyConstructor ( ) {
183+ CollectionOfConstantsEmptyConstructor ( ) {
150184 this .getConstructedType ( )
151185 .getSourceDeclaration ( )
152186 .getASourceSupertype * ( )
153- .hasQualifiedName ( "java.util" , "List" ) and
187+ .hasQualifiedName ( "java.util" , collectionClass ) and
154188 exists ( Constructor c | c = this .getConstructor ( ) |
155189 c .hasNoParameters ( )
156190 or
157191 c .getNumberOfParameters ( ) = 1 and
158192 c .getParameter ( 0 ) .getType ( ) .( PrimitiveType ) .hasName ( "int" )
193+ or
194+ c .getNumberOfParameters ( ) = 2 and
195+ c .getParameter ( 0 ) .getType ( ) .( PrimitiveType ) .hasName ( "int" ) and
196+ c .getParameter ( 0 ) .getType ( ) .( PrimitiveType ) .hasName ( "float" )
159197 )
160198 }
161199
162200 override predicate isImmutable ( ) { none ( ) }
163201 }
164202
165203 /**
166- * A invocation of a constructor of a type that extends `java.util.List`
167- * which constructs an empty mutable list.
204+ * A invocation of a constructor of a type that extends `java.util.List` or
205+ * `java.util.Set` which constructs a non- empty mutable list.
168206 */
169- private class JavaUtilListOfConstantsNonEmptyConstructor extends ClassInstanceExpr ,
170- JavaUtilListOfConstants
207+ private class CollectionOfConstantsNonEmptyConstructor extends ClassInstanceExpr ,
208+ CollectionOfConstants
171209 {
172- JavaUtilListOfConstantsNonEmptyConstructor ( ) {
210+ CollectionOfConstantsNonEmptyConstructor ( ) {
173211 this .getConstructedType ( )
174212 .getSourceDeclaration ( )
175213 .getASourceSupertype * ( )
176- .hasQualifiedName ( "java.util" , "List" ) and
214+ .hasQualifiedName ( "java.util" , collectionClass ) and
177215 exists ( Constructor c | c = this .getConstructor ( ) |
178216 c .getNumberOfParameters ( ) = 1 and
179217 c .getParameter ( 0 )
@@ -182,7 +220,7 @@ module JavaUtilList {
182220 .getASourceSupertype * ( )
183221 .hasQualifiedName ( "java.util" , "Collection" )
184222 ) and
185- javaUtilListOfConstantsFlowsTo ( this .getArgument ( 0 ) )
223+ collectionOfConstantsFlowsTo ( _ , this .getArgument ( 0 ) )
186224 }
187225
188226 override predicate isImmutable ( ) { none ( ) }
@@ -191,11 +229,15 @@ module JavaUtilList {
191229 /**
192230 * A invocation of `java.util.Arrays.asList` which constructs a mutable list.
193231 */
194- private class JavaUtilArraysAsList extends MethodCall , JavaUtilListOfConstants {
232+ private class JavaUtilArraysAsList extends MethodCall , CollectionOfConstants {
195233 JavaUtilArraysAsList ( ) {
234+ collectionClass = "List" and
196235 exists ( Method m | this .getMethod ( ) = m |
197236 m .hasName ( "asList" ) and
198- m .getDeclaringType ( ) .getSourceDeclaration ( ) .hasQualifiedName ( "java.util" , "Arrays" )
237+ m .getDeclaringType ( )
238+ .getSourceDeclaration ( )
239+ .getASourceSupertype * ( )
240+ .hasQualifiedName ( "java.util" , "Arrays" )
199241 ) and
200242 methodCallHasConstantArguments ( this )
201243 }
@@ -207,12 +249,14 @@ module JavaUtilList {
207249 * An invocation of `java.util.List.of` which constructs an immutable list
208250 * which contains only compile-time constants.
209251 */
210- private class JavaUtilListOfConstantsCreatedWithListOf extends MethodCall , JavaUtilListOfConstants
211- {
212- JavaUtilListOfConstantsCreatedWithListOf ( ) {
252+ private class CollectionOfConstantsCreatedWithOf extends MethodCall , CollectionOfConstants {
253+ CollectionOfConstantsCreatedWithOf ( ) {
213254 exists ( Method m | this .getMethod ( ) = m |
214255 m .hasName ( "of" ) and
215- m .getDeclaringType ( ) .getSourceDeclaration ( ) .hasQualifiedName ( "java.util" , "List" )
256+ m .getDeclaringType ( )
257+ .getSourceDeclaration ( )
258+ .getASourceSupertype * ( )
259+ .hasQualifiedName ( "java.util" , collectionClass )
216260 ) and
217261 methodCallHasConstantArguments ( this )
218262 }
@@ -221,19 +265,23 @@ module JavaUtilList {
221265 }
222266
223267 /**
224- * An invocation of `java.util.Collections.unmodifiableList` which constructs an immutable list
225- * which contains only compile-time constants.
268+ * An invocation of `java.util.Collections.unmodifiableList` or
269+ * `java.util.Collections.unmodifiableSet` which constructs an immutable
270+ * list/set which contains only compile-time constants.
226271 */
227- private class JavaUtilListOfConstantsCreatedWithCollectionsUnmodifiableList extends MethodCall ,
228- JavaUtilListOfConstants
272+ private class CollectionOfConstantsCreatedWithCollectionsUnmodifiableList extends MethodCall ,
273+ CollectionOfConstants
229274 {
230- JavaUtilListOfConstantsCreatedWithCollectionsUnmodifiableList ( ) {
275+ CollectionOfConstantsCreatedWithCollectionsUnmodifiableList ( ) {
231276 exists ( Method m |
232- m .hasName ( "unmodifiableList" ) and
233- m .getDeclaringType ( ) .getSourceDeclaration ( ) .hasQualifiedName ( "java.util" , "Collections" ) and
277+ m .hasName ( "unmodifiable" + collectionClass ) and
278+ m .getDeclaringType ( )
279+ .getSourceDeclaration ( )
280+ .getASourceSupertype * ( )
281+ .hasQualifiedName ( "java.util" , "Collections" ) and
234282 this .getMethod ( ) = m
235283 |
236- javaUtilListOfConstantsFlowsTo ( this .getArgument ( 0 ) )
284+ collectionOfConstantsFlowsTo ( collectionClass , this .getArgument ( 0 ) )
237285 )
238286 }
239287
0 commit comments