diff --git a/ruby/ql/consistency-queries/DataFlowConsistency.ql b/ruby/ql/consistency-queries/DataFlowConsistency.ql index d064eeb3701d..c0dd1757128c 100644 --- a/ruby/ql/consistency-queries/DataFlowConsistency.ql +++ b/ruby/ql/consistency-queries/DataFlowConsistency.ql @@ -43,6 +43,10 @@ private module Input implements InputSig { arg.asExpr().getASuccessor(any(SuccessorTypes::ConditionalSuccessor c)).getASuccessor*() = n and n.getASplit() instanceof Split::ConditionalCompletionSplit ) + or + // Synthetic block parameter nodes are passed directly as lambda-self reference + // arguments to all `yield` calls + arg instanceof ArgumentNodes::BlockParameterArgumentNode } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 010067604e93..f53fb80fcea7 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -916,7 +916,7 @@ private module ParameterNodes { * The value of a block parameter at function entry, viewed as a node in a data * flow graph. */ - class BlockParameterNode extends ParameterNodeImpl, ArgumentNode, TBlockParameterNode { + class BlockParameterNode extends ParameterNodeImpl, TBlockParameterNode { private MethodBase method; BlockParameterNode() { this = TBlockParameterNode(method) } @@ -935,16 +935,6 @@ private module ParameterNodes { this.getMethod() = result.getExpr().(YieldCall).getEnclosingMethod() } - // needed for variable capture flow - override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) { - call = this.getAYieldCall() and - pos.isLambdaSelf() - } - - override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - this.sourceArgumentOf(call.asCall(), pos) - } - override CfgScope getCfgScope() { result = method } override Location getLocationImpl() { @@ -1199,7 +1189,7 @@ abstract class ArgumentNode extends Node { final DataFlowCall getCall() { this.argumentOf(result, _) } } -private module ArgumentNodes { +module ArgumentNodes { /** A data-flow node that represents an explicit call argument. */ class ExplicitArgumentNode extends ArgumentNode { Argument arg; @@ -1215,6 +1205,20 @@ private module ArgumentNodes { } } + class BlockParameterArgumentNode extends BlockParameterNode, ArgumentNode { + BlockParameterArgumentNode() { exists(this.getAYieldCall()) } + + // needed for variable capture flow + override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) { + call = this.getAYieldCall() and + pos.isLambdaSelf() + } + + override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { + this.sourceArgumentOf(call.asCall(), pos) + } + } + private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode { private DataFlowCall call_; private ArgumentPosition pos_;