diff --git a/ql/src/codeql_ruby/controlflow/CfgNodes.qll b/ql/src/codeql_ruby/controlflow/CfgNodes.qll index c6779e99c5b..3245c04e8f3 100644 --- a/ql/src/codeql_ruby/controlflow/CfgNodes.qll +++ b/ql/src/codeql_ruby/controlflow/CfgNodes.qll @@ -160,15 +160,15 @@ abstract private class ExprChildMapping extends Expr { /** Provides classes for control-flow nodes that wrap AST expressions. */ module ExprNodes { // TODO: Add more classes - private class AssignmentExprChildMapping extends ExprChildMapping, Assignment { + private class AssignExprChildMapping extends ExprChildMapping, AssignExpr { override predicate relevantChild(Expr e) { e = this.getAnOperand() } } - /** A control-flow node that wraps an `Assignment` AST expression. */ - class AssignmentCfgNode extends ExprCfgNode { - override AssignmentExprChildMapping e; + /** A control-flow node that wraps an `AssignExpr` AST expression. */ + class AssignExprCfgNode extends ExprCfgNode { + override AssignExprChildMapping e; - final override Assignment getExpr() { result = ExprCfgNode.super.getExpr() } + final override AssignExpr getExpr() { result = ExprCfgNode.super.getExpr() } /** Gets the LHS of this assignment. */ final ExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) } @@ -177,11 +177,6 @@ module ExprNodes { final ExprCfgNode getRhs() { e.hasCfgChild(e.getRightOperand(), this, result) } } - /** A control-flow node that wraps an `AssignExpr` AST expression. */ - class AssignExprCfgNode extends AssignmentCfgNode { - AssignExprCfgNode() { this.getExpr() instanceof AssignExpr } - } - private class OperationExprChildMapping extends ExprChildMapping, Operation { override predicate relevantChild(Expr e) { e = this.getAnOperand() } } diff --git a/ql/src/codeql_ruby/dataflow/SSA.qll b/ql/src/codeql_ruby/dataflow/SSA.qll index e83927e5de6..0ddbe1ef5a1 100644 --- a/ql/src/codeql_ruby/dataflow/SSA.qll +++ b/ql/src/codeql_ruby/dataflow/SSA.qll @@ -203,6 +203,18 @@ module Ssa { /** Gets the underlying write access. */ final VariableWriteAccess getWriteAccess() { result = write } + /** + * Holds if this SSA definition represents a direct assignment of `value` + * to the underlying variable. + */ + predicate assigns(CfgNodes::ExprCfgNode value) { + exists(CfgNodes::ExprNodes::AssignExprCfgNode a, BasicBlock bb, int i | + this.definesAt(_, bb, i) and + a = bb.getNode(i) and + value = a.getRhs() + ) + } + final override string toString() { result = Definition.super.toString() } final override Location getLocation() { result = this.getControlFlowNode().getLocation() } diff --git a/ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll b/ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll index bad97b4d907..552ffb7b82b 100644 --- a/ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll @@ -58,13 +58,8 @@ module LocalFlow { ) or // Flow from assignment into SSA definition - exists(CfgNodes::ExprNodes::AssignmentCfgNode a, BasicBlock bb, int i | - def.definesAt(_, bb, i) and - a = bb.getNode(i) and - a.getExpr() instanceof AssignExpr and - nodeFrom.asExpr() = a.getRhs() and - nodeTo.(SsaDefinitionNode).getDefinition() = def - ) + def.(Ssa::WriteDefinition).assigns(nodeFrom.asExpr()) and + nodeTo.(SsaDefinitionNode).getDefinition() = def or // Flow from SSA definition to first read def = nodeFrom.(SsaDefinitionNode).getDefinition() and