Skip to content

Commit b820f3f

Browse files
authored
Merge pull request #212 from github/hvitved/ssa/assigns-pred
Add `Ssa::WriteDefinition::assigns/1` predicate
2 parents 78db1bf + 7cc02e6 commit b820f3f

3 files changed

Lines changed: 19 additions & 17 deletions

File tree

ql/src/codeql_ruby/controlflow/CfgNodes.qll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,15 @@ abstract private class ExprChildMapping extends Expr {
160160
/** Provides classes for control-flow nodes that wrap AST expressions. */
161161
module ExprNodes {
162162
// TODO: Add more classes
163-
private class AssignmentExprChildMapping extends ExprChildMapping, Assignment {
163+
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
164164
override predicate relevantChild(Expr e) { e = this.getAnOperand() }
165165
}
166166

167-
/** A control-flow node that wraps an `Assignment` AST expression. */
168-
class AssignmentCfgNode extends ExprCfgNode {
169-
override AssignmentExprChildMapping e;
167+
/** A control-flow node that wraps an `AssignExpr` AST expression. */
168+
class AssignExprCfgNode extends ExprCfgNode {
169+
override AssignExprChildMapping e;
170170

171-
final override Assignment getExpr() { result = ExprCfgNode.super.getExpr() }
171+
final override AssignExpr getExpr() { result = ExprCfgNode.super.getExpr() }
172172

173173
/** Gets the LHS of this assignment. */
174174
final ExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) }
@@ -177,11 +177,6 @@ module ExprNodes {
177177
final ExprCfgNode getRhs() { e.hasCfgChild(e.getRightOperand(), this, result) }
178178
}
179179

180-
/** A control-flow node that wraps an `AssignExpr` AST expression. */
181-
class AssignExprCfgNode extends AssignmentCfgNode {
182-
AssignExprCfgNode() { this.getExpr() instanceof AssignExpr }
183-
}
184-
185180
private class OperationExprChildMapping extends ExprChildMapping, Operation {
186181
override predicate relevantChild(Expr e) { e = this.getAnOperand() }
187182
}

ql/src/codeql_ruby/dataflow/SSA.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ module Ssa {
203203
/** Gets the underlying write access. */
204204
final VariableWriteAccess getWriteAccess() { result = write }
205205

206+
/**
207+
* Holds if this SSA definition represents a direct assignment of `value`
208+
* to the underlying variable.
209+
*/
210+
predicate assigns(CfgNodes::ExprCfgNode value) {
211+
exists(CfgNodes::ExprNodes::AssignExprCfgNode a, BasicBlock bb, int i |
212+
this.definesAt(_, bb, i) and
213+
a = bb.getNode(i) and
214+
value = a.getRhs()
215+
)
216+
}
217+
206218
final override string toString() { result = Definition.super.toString() }
207219

208220
final override Location getLocation() { result = this.getControlFlowNode().getLocation() }

ql/src/codeql_ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,8 @@ module LocalFlow {
5858
)
5959
or
6060
// Flow from assignment into SSA definition
61-
exists(CfgNodes::ExprNodes::AssignmentCfgNode a, BasicBlock bb, int i |
62-
def.definesAt(_, bb, i) and
63-
a = bb.getNode(i) and
64-
a.getExpr() instanceof AssignExpr and
65-
nodeFrom.asExpr() = a.getRhs() and
66-
nodeTo.(SsaDefinitionNode).getDefinition() = def
67-
)
61+
def.(Ssa::WriteDefinition).assigns(nodeFrom.asExpr()) and
62+
nodeTo.(SsaDefinitionNode).getDefinition() = def
6863
or
6964
// Flow from SSA definition to first read
7065
def = nodeFrom.(SsaDefinitionNode).getDefinition() and

0 commit comments

Comments
 (0)