@@ -18,6 +18,98 @@ private Callable dispatchCand(Call c) {
1818 result = viableImpl_inp ( c )
1919}
2020
21+ /**
22+ * Holds if `t` and all its enclosing types are public.
23+ */
24+ private predicate veryPublic ( RefType t ) {
25+ t .isPublic ( ) and
26+ (
27+ not t instanceof NestedType or
28+ veryPublic ( t .( NestedType ) .getEnclosingType ( ) )
29+ )
30+ }
31+
32+ /**
33+ * Holds if `cie` occurs as the initializer of a public static field.
34+ */
35+ private predicate publicStaticFieldInit ( ClassInstanceExpr cie ) {
36+ exists ( Field f |
37+ f .isStatic ( ) and
38+ f .isPublic ( ) and
39+ veryPublic ( f .getDeclaringType ( ) ) and
40+ f .getInitializer ( ) = cie
41+ )
42+ }
43+
44+ /**
45+ * Holds if a `ClassInstanceExpr` constructing `t` occurs as the initializer of
46+ * a public static field.
47+ */
48+ private predicate publicThroughField ( RefType t ) {
49+ exists ( ClassInstanceExpr cie |
50+ cie .getConstructedType ( ) = t and
51+ publicStaticFieldInit ( cie )
52+ )
53+ }
54+
55+ /**
56+ * Holds if `t` and its subtypes are private or anonymous.
57+ */
58+ private predicate privateConstruction ( RefType t ) {
59+ ( t .isPrivate ( ) or t instanceof AnonymousClass ) and
60+ not publicThroughField ( t ) and
61+ forall ( SrcRefType sub | sub .getASourceSupertype + ( ) = t .getSourceDeclaration ( ) |
62+ ( sub .isPrivate ( ) or sub instanceof AnonymousClass ) and
63+ not publicThroughField ( sub )
64+ )
65+ }
66+
67+ /**
68+ * Holds if `m` is declared on a type that we will track all instantiations of
69+ * for the purpose of virtual dispatch to `m`. This holds in particular for
70+ * lambda methods and methods on other anonymous classes.
71+ */
72+ private predicate trackedMethod ( Method m ) {
73+ privateConstruction ( m .getDeclaringType ( ) .getSourceDeclaration ( ) )
74+ }
75+
76+ /**
77+ * Holds if `t` declares or inherits the tracked method `m`.
78+ */
79+ private predicate trackedMethodOnType ( Method m , SrcRefType t ) {
80+ exists ( Method m0 |
81+ t .hasMethod ( m0 , _, _) and
82+ m = m0 .getSourceDeclaration ( ) and
83+ trackedMethod ( m )
84+ )
85+ }
86+
87+ /**
88+ * Holds if `ma` may dispatch to the tracked method `m` declared or inherited
89+ * by the type constructed by `cie`. Thus the dispatch from `ma` to `m` will
90+ * only be included if `cie` flows to the qualifier of `ma`.
91+ */
92+ private predicate dispatchOrigin ( ClassInstanceExpr cie , MethodAccess ma , Method m ) {
93+ m = viableImpl_inp ( ma ) and
94+ not m = ma .getMethod ( ) .getSourceDeclaration ( ) and
95+ trackedMethodOnType ( m , cie .getConstructedType ( ) .getSourceDeclaration ( ) )
96+ }
97+
98+ /** Holds if `t` is a type that is relevant for dispatch flow. */
99+ private predicate relevant ( RefType t ) {
100+ exists ( ClassInstanceExpr cie | dispatchOrigin ( cie , _, _) and t = cie .getConstructedType ( ) .getSourceDeclaration ( ) ) or
101+ relevant ( t .getErasure ( ) ) or
102+ exists ( RefType r | relevant ( r ) and t = r .getASourceSupertype ( ) ) or
103+ relevant ( t .( Array ) .getComponentType ( ) ) or
104+ t instanceof MapType or
105+ t instanceof CollectionType
106+ }
107+
108+ /** A node with a type that is relevant for dispatch flow. */
109+ private class RelevantNode extends Node {
110+ RelevantNode ( ) { relevant ( this .getType ( ) ) }
111+ }
112+
21113/**
22114 * Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
23115 * The instance parameter is considered to have index `-1`.
@@ -26,7 +118,8 @@ pragma[nomagic]
26118private predicate viableParamCand ( Call call , int i , ParameterNode p ) {
27119 exists ( Callable callable |
28120 callable = dispatchCand ( call ) and
29- p .isParameterOf ( callable , i )
121+ p .isParameterOf ( callable , i ) and
122+ p instanceof RelevantNode
30123 )
31124}
32125
@@ -43,7 +136,7 @@ private predicate viableArgParamCand(ArgumentNode arg, ParameterNode p) {
43136/**
44137 * Holds if data may flow from `n1` to `n2` in a single step through a call or a return.
45138 */
46- private predicate callFlowStepCand ( Node n1 , Node n2 ) {
139+ private predicate callFlowStepCand ( RelevantNode n1 , RelevantNode n2 ) {
47140 exists ( ReturnStmt ret , Method m |
48141 ret .getEnclosingCallable ( ) = m and
49142 ret .getResult ( ) = n1 .asExpr ( ) and
@@ -56,7 +149,7 @@ private predicate callFlowStepCand(Node n1, Node n2) {
56149 * Holds if data may flow from `n1` to `n2` in a single step that does not go
57150 * through a call or a return.
58151 */
59- private predicate flowStep ( Node n1 , Node n2 ) {
152+ private predicate flowStep ( RelevantNode n1 , RelevantNode n2 ) {
60153 exists ( BaseSsaVariable v , BaseSsaVariable def |
61154 def .( BaseSsaUpdate ) .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) = n1 .asExpr ( ) or
62155 def .( BaseSsaImplicitInit ) .isParameterDefinition ( n1 .asParameter ( ) ) or
@@ -126,83 +219,6 @@ private predicate flowStep(Node n1, Node n2) {
126219 )
127220}
128221
129- /**
130- * Holds if `t` and all its enclosing types are public.
131- */
132- private predicate veryPublic ( RefType t ) {
133- t .isPublic ( ) and
134- (
135- not t instanceof NestedType or
136- veryPublic ( t .( NestedType ) .getEnclosingType ( ) )
137- )
138- }
139-
140- /**
141- * Holds if `cie` occurs as the initializer of a public static field.
142- */
143- private predicate publicStaticFieldInit ( ClassInstanceExpr cie ) {
144- exists ( Field f |
145- f .isStatic ( ) and
146- f .isPublic ( ) and
147- veryPublic ( f .getDeclaringType ( ) ) and
148- f .getInitializer ( ) = cie
149- )
150- }
151-
152- /**
153- * Holds if a `ClassInstanceExpr` constructing `t` occurs as the initializer of
154- * a public static field.
155- */
156- private predicate publicThroughField ( RefType t ) {
157- exists ( ClassInstanceExpr cie |
158- cie .getConstructedType ( ) = t and
159- publicStaticFieldInit ( cie )
160- )
161- }
162-
163- /**
164- * Holds if `t` and its subtypes are private or anonymous.
165- */
166- private predicate privateConstruction ( RefType t ) {
167- ( t .isPrivate ( ) or t instanceof AnonymousClass ) and
168- not publicThroughField ( t ) and
169- forall ( SrcRefType sub | sub .getASourceSupertype + ( ) = t .getSourceDeclaration ( ) |
170- ( sub .isPrivate ( ) or sub instanceof AnonymousClass ) and
171- not publicThroughField ( sub )
172- )
173- }
174-
175- /**
176- * Holds if `m` is declared on a type that we will track all instantiations of
177- * for the purpose of virtual dispatch to `m`. This holds in particular for
178- * lambda methods and methods on other anonymous classes.
179- */
180- private predicate trackedMethod ( Method m ) {
181- privateConstruction ( m .getDeclaringType ( ) .getSourceDeclaration ( ) )
182- }
183-
184- /**
185- * Holds if `t` declares or inherits the tracked method `m`.
186- */
187- private predicate trackedMethodOnType ( Method m , SrcRefType t ) {
188- exists ( Method m0 |
189- t .hasMethod ( m0 , _, _) and
190- m = m0 .getSourceDeclaration ( ) and
191- trackedMethod ( m )
192- )
193- }
194-
195- /**
196- * Holds if `ma` may dispatch to the tracked method `m` declared or inherited
197- * by the type constructed by `cie`. Thus the dispatch from `ma` to `m` will
198- * only be included if `cie` flows to the qualifier of `ma`.
199- */
200- private predicate dispatchOrigin ( ClassInstanceExpr cie , MethodAccess ma , Method m ) {
201- m = viableImpl_inp ( ma ) and
202- not m = ma .getMethod ( ) .getSourceDeclaration ( ) and
203- trackedMethodOnType ( m , cie .getConstructedType ( ) .getSourceDeclaration ( ) )
204- }
205-
206222/**
207223 * Holds if `n` is forward-reachable from a relevant `ClassInstanceExpr`.
208224 */
0 commit comments