@@ -81,21 +81,20 @@ class InvokeNode extends DataFlow::DefaultSourceNode {
8181 }
8282
8383 /** Gets an abstract value representing possible callees of this call site. */
84- cached
85- AbstractValue getACalleeValue ( ) { result = impl .getCalleeNode ( ) .analyze ( ) .getAValue ( ) }
86-
87- /** Gets a potential callee based on dataflow analysis results. */
88- private Function getACalleeFromDataflow ( ) {
89- result = getACalleeValue ( ) .( AbstractCallable ) .getFunction ( )
90- }
84+ AbstractValue getACalleeValue ( ) { result = InvokeNode:: getACalleeValue ( this ) }
9185
9286 /** Gets a potential callee of this call site. */
93- Function getACallee ( ) {
94- result = getACalleeFromDataflow ( )
95- or
96- not exists ( getACalleeFromDataflow ( ) ) and
97- result = impl .( DataFlow:: Impl:: ExplicitInvokeNode ) .asExpr ( ) .( InvokeExpr ) .getResolvedCallee ( )
98- }
87+ Function getACallee ( ) { result = InvokeNode:: getACallee ( this ) }
88+
89+ /**
90+ * Gets a callee of this call site where `imprecision` is a heuristic measure of how
91+ * likely it is that `callee` is only suggested as a potential callee due to
92+ * imprecise analysis of global variables and is not, in fact, a viable callee at all.
93+ *
94+ * Callees with imprecision zero, in particular, have either been derived without
95+ * considering global variables, or are calls to a global variable within the same file.
96+ */
97+ Function getACallee ( int imprecision ) { result = InvokeNode:: getACallee ( this , imprecision ) }
9998
10099 /**
101100 * Holds if the approximation of possible callees for this call site is
@@ -136,6 +135,60 @@ class InvokeNode extends DataFlow::DefaultSourceNode {
136135 predicate isUncertain ( ) { isImprecise ( ) or isIncomplete ( ) }
137136}
138137
138+ /** Auxiliary module used to cache a few related predicates together. */
139+ cached
140+ private module InvokeNode {
141+ /** Gets an abstract value representing possible callees of `invk`. */
142+ cached
143+ AbstractValue getACalleeValue ( InvokeNode invk ) {
144+ result = invk .getCalleeNode ( ) .analyze ( ) .getAValue ( )
145+ }
146+
147+ /** Gets a potential callee of `invk` based on dataflow analysis results. */
148+ private Function getACalleeFromDataflow ( InvokeNode invk ) {
149+ result = getACalleeValue ( invk ) .( AbstractCallable ) .getFunction ( )
150+ }
151+
152+ /** Gets a potential callee of `invk`. */
153+ cached
154+ Function getACallee ( InvokeNode invk ) {
155+ result = getACalleeFromDataflow ( invk )
156+ or
157+ not exists ( getACalleeFromDataflow ( invk ) ) and
158+ result = invk .( DataFlow:: Impl:: ExplicitInvokeNode ) .asExpr ( ) .( InvokeExpr ) .getResolvedCallee ( )
159+ }
160+
161+ /**
162+ * Gets a callee of `invk` where `imprecision` is a heuristic measure of how
163+ * likely it is that `callee` is only suggested as a potential callee due to
164+ * imprecise analysis of global variables and is not, in fact, a viable callee at all.
165+ *
166+ * Callees with imprecision zero, in particular, have either been derived without
167+ * considering global variables, or are calls to a global variable within the same file.
168+ */
169+ cached
170+ Function getACallee ( InvokeNode invk , int imprecision ) {
171+ result = getACallee ( invk ) and
172+ (
173+ // if global flow was used to derive the callee, we may be imprecise
174+ if invk .isIndefinite ( "global" )
175+ then
176+ // callees within the same file are probably genuine
177+ result .getFile ( ) = invk .getFile ( ) and imprecision = 0
178+ or
179+ // calls to global functions declared in an externs file are fairly
180+ // safe as well
181+ result .inExternsFile ( ) and imprecision = 1
182+ or
183+ // otherwise we make worst-case assumptions
184+ imprecision = 2
185+ else
186+ // no global flow, so no imprecision
187+ imprecision = 0
188+ )
189+ }
190+ }
191+
139192/** A data flow node corresponding to a function call without `new`. */
140193class CallNode extends InvokeNode {
141194 override DataFlow:: Impl:: CallNodeDef impl ;
0 commit comments