@@ -231,10 +231,36 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
231231 * Holds if the set of viable implementations that can be called by `call`
232232 * might be improved by knowing the call context.
233233 */
234- predicate mayBenefitFromCallContext ( CallInstruction call , Function f ) { none ( ) }
234+ predicate mayBenefitFromCallContext ( CallInstruction call , Function f ) {
235+ mayBenefitFromCallContext ( call , f , _)
236+ }
237+
238+ /**
239+ * Holds if `call` is a call through a function pointer, and the pointer
240+ * value is given as the `arg`'th argument to `f`.
241+ *
242+ * Note that `f` may be several layers up through the call chain.
243+ */
244+ private predicate mayBenefitFromCallContext (
245+ VirtualDispatch:: DataSensitiveCall call , Function f , int arg
246+ ) {
247+ exists ( InitializeParameterInstruction init |
248+ not exists ( call .getStaticCallTarget ( ) ) and
249+ init .getEnclosingFunction ( ) = f and
250+ call .flowsFrom ( DataFlow:: instructionNode ( init ) , _) and
251+ init .getParameter ( ) .getIndex ( ) = arg
252+ )
253+ }
235254
236255/**
237256 * Gets a viable dispatch target of `call` in the context `ctx`. This is
238257 * restricted to those `call`s for which a context might make a difference.
239258 */
240- Function viableImplInCallContext ( CallInstruction call , CallInstruction ctx ) { none ( ) }
259+ Function viableImplInCallContext ( CallInstruction call , CallInstruction ctx ) {
260+ result = viableCallable ( call ) and
261+ exists ( int i , Function f |
262+ mayBenefitFromCallContext ( pragma [ only_bind_into ] ( call ) , f , i ) and
263+ f = ctx .getStaticCallTarget ( ) and
264+ result = ctx .getArgument ( i ) .getUnconvertedResultExpression ( ) .( FunctionAccess ) .getTarget ( )
265+ )
266+ }
0 commit comments