@@ -231,10 +231,36 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
231
231
* Holds if the set of viable implementations that can be called by `call`
232
232
* might be improved by knowing the call context.
233
233
*/
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
+ }
235
254
236
255
/**
237
256
* Gets a viable dispatch target of `call` in the context `ctx`. This is
238
257
* restricted to those `call`s for which a context might make a difference.
239
258
*/
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