@@ -689,10 +689,24 @@ private predicate summarizedHigherOrderCall(
689689 * Holds if `arg` is passed as the `i`th argument to `callback` through a callback invocation.
690690 *
691691 * This can be a summarized call, that is, `arg` and `callback` flow into a call,
692- * `f(arg, callback)`, which performs the invocation.
692+ * `f(arg, callback)`, which performs the invocation.
693693 *
694694 * Alternatively, the callback can flow into a call `f(callback)` which itself provides the `arg`.
695695 * That is, `arg` refers to a value defined in `f` or one of its callees.
696+ *
697+ * In the latter case, the summary will consists of both a `return` and `call` step, for the following reasons:
698+ *
699+ * - Having `return` in the summary ensures that arguments passsed to `f` can't propagate back out along this edge.
700+ * This is, `arg` should be defined in `f` or one of its callees, since a context-dependent value (i.e. parameter)
701+ * should not propagate to every callback passed to `f`.
702+ * In reality, `arg` may refer to a parameter, but in that case, the `return` summary prevents the edge from ever
703+ * being used.
704+ *
705+ * - Having `call` in the summary ensures that values we propagate into the callback definition along this edge
706+ * can't propagate out to other callers of that function through a return statement.
707+ *
708+ * - The flow label mapping of the summary corresponds to the transformation from `arg` to the
709+ * invocation of the callback.
696710 */
697711predicate higherOrderCall (
698712 DataFlow:: Node arg , DataFlow:: SourceNode callback , int i , DataFlow:: Configuration cfg ,
@@ -713,13 +727,11 @@ predicate higherOrderCall(
713727 )
714728 or
715729 // Forwarding of the callback parameter (but not the argument).
716- // We use a return summary since flow moves back towards the call site.
717- // This ensures that an argument that is only tainted in some contexts cannot flow
718- // out to every callback.
719730 exists ( DataFlow:: Node cbArg , DataFlow:: SourceNode innerCb , PathSummary oldSummary |
720731 higherOrderCall ( arg , innerCb , i , cfg , oldSummary ) and
721732 callStep ( cbArg , innerCb ) and
722733 callback .flowsTo ( cbArg ) and
734+ // Prepend a 'return' summary to prevent context-dependent values (i.e. parameters) from using this edge.
723735 summary = PathSummary:: return ( ) .append ( oldSummary )
724736 )
725737}
0 commit comments