Skip to content

Commit e948e22

Browse files
committed
Ruby: all Exprs have a corresponding DataFlow::Node that is more specific than just DataFlow::ExprNode
1 parent aac65b0 commit e948e22

File tree

2 files changed

+129
-1
lines changed

2 files changed

+129
-1
lines changed

ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,35 @@ module ExprNodes {
243243
override Literal getExpr() { result = super.getExpr() }
244244
}
245245

246+
private class ControlExprChildMapping extends ExprChildMapping, ControlExpr {
247+
override predicate relevantChild(AstNode n) { none() }
248+
}
249+
250+
/** A control-flow node that wraps a `ControlExpr` AST expression. */
251+
class ControlExprCfgNode extends ExprCfgNode {
252+
override string getAPrimaryQlClass() { result = "ControlExprCfgNode" }
253+
254+
override ControlExprChildMapping e;
255+
256+
override ControlExpr getExpr() { result = super.getExpr() }
257+
}
258+
259+
private class LhsExprChildMapping extends ExprChildMapping, LhsExpr {
260+
override predicate relevantChild(AstNode n) { none() }
261+
}
262+
263+
/** A control-flow node that wraps a `LhsExpr` AST expression. */
264+
class LhsExprCfgNode extends ExprCfgNode {
265+
override string getAPrimaryQlClass() { result = "LhsExprCfgNode" }
266+
267+
override LhsExprChildMapping e;
268+
269+
override LhsExpr getExpr() { result = super.getExpr() }
270+
271+
/** Gets a variable used in (or introduced by) this LHS. */
272+
Variable getAVariable() { result = e.(VariableAccess).getVariable() }
273+
}
274+
246275
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
247276
override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
248277
}
@@ -256,7 +285,7 @@ module ExprNodes {
256285
final override AssignExpr getExpr() { result = ExprCfgNode.super.getExpr() }
257286

258287
/** Gets the LHS of this assignment. */
259-
final ExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) }
288+
final LhsExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) }
260289

261290
/** Gets the RHS of this assignment. */
262291
final ExprCfgNode getRhs() { e.hasCfgChild(e.getRightOperand(), this, result) }

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,105 @@ class ClassNode extends ModuleNode {
984984
ClassNode() { this.isClass() }
985985
}
986986

987+
/**
988+
* A data flow node corresponding to a literal expression.
989+
*/
990+
class LiteralNode extends ExprNode {
991+
private CfgNodes::ExprNodes::LiteralCfgNode literalCfgNode;
992+
993+
LiteralNode() { this.asExpr() = literalCfgNode }
994+
995+
/** Gets the underlying AST node as a `Literal`. */
996+
Literal asLiteralAstNode() { result = literalCfgNode.getExpr() }
997+
}
998+
999+
/**
1000+
* A data flow node corresponding to an operation expression.
1001+
*/
1002+
class OperationNode extends ExprNode {
1003+
private CfgNodes::ExprNodes::OperationCfgNode operationCfgNode;
1004+
1005+
OperationNode() { this.asExpr() = operationCfgNode }
1006+
1007+
/** Gets the underlying AST node as an `Operation`. */
1008+
Operation asOperationAstNode() { result = operationCfgNode.getExpr() }
1009+
1010+
/** Gets the operator of this operation. */
1011+
final string getOperator() { result = operationCfgNode.getOperator() }
1012+
1013+
/** Gets an operand of this operation. */
1014+
final Node getAnOperand() { result.asExpr() = operationCfgNode.getAnOperand() }
1015+
}
1016+
1017+
/**
1018+
* A data flow node corresponding to a control expression (e.g. `if`, `while`, `for`).
1019+
*/
1020+
class ControlExprNode extends ExprNode {
1021+
private CfgNodes::ExprNodes::ControlExprCfgNode controlExprCfgNode;
1022+
1023+
ControlExprNode() { this.asExpr() = controlExprCfgNode }
1024+
1025+
/** Gets the underlying AST node as a `ControlExpr`. */
1026+
ControlExpr asControlExprAstNode() { result = controlExprCfgNode.getExpr() }
1027+
}
1028+
1029+
/**
1030+
* A data flow node corresponding to a variable access expression.
1031+
*/
1032+
class VariableAccessNode extends ExprNode {
1033+
private CfgNodes::ExprNodes::VariableAccessCfgNode variableAccessCfgNode;
1034+
1035+
VariableAccessNode() { this.asExpr() = variableAccessCfgNode }
1036+
1037+
/** Gets the underlying AST node as a `VariableAccess`. */
1038+
VariableAccess asVariableAccessAstNode() { result = variableAccessCfgNode.getExpr() }
1039+
}
1040+
1041+
/**
1042+
* A data flow node corresponding to a constant access expression.
1043+
*/
1044+
class ConstantAccessNode extends ExprNode {
1045+
private CfgNodes::ExprNodes::ConstantAccessCfgNode constantAccessCfgNode;
1046+
1047+
ConstantAccessNode() { this.asExpr() = constantAccessCfgNode }
1048+
1049+
/** Gets the underlying AST node as a `ConstantAccess`. */
1050+
ConstantAccess asConstantAccessAstNode() { result = constantAccessCfgNode.getExpr() }
1051+
1052+
/** Gets the node corresponding to the scope expression. */
1053+
final Node getScopeNode() { result.asExpr() = constantAccessCfgNode.getScopeExpr() }
1054+
}
1055+
1056+
/**
1057+
* A data flow node corresponding to a LHS expression.
1058+
*/
1059+
class LhsExprNode extends ExprNode {
1060+
private CfgNodes::ExprNodes::LhsExprCfgNode lhsExprCfgNode;
1061+
1062+
LhsExprNode() { this.asExpr() = lhsExprCfgNode }
1063+
1064+
/** Gets the underlying AST node as a `LhsExpr`. */
1065+
LhsExpr asLhsExprAstNode() { result = lhsExprCfgNode.getExpr() }
1066+
1067+
/** Gets a variable used in (or introduced by) this LHS. */
1068+
Variable getAVariable() { result = lhsExprCfgNode.getAVariable() }
1069+
}
1070+
1071+
/**
1072+
* A data flow node corresponding to a statement sequence expression.
1073+
*/
1074+
class StmtSequenceNode extends ExprNode {
1075+
private CfgNodes::ExprNodes::StmtSequenceCfgNode stmtSequenceCfgNode;
1076+
1077+
StmtSequenceNode() { this.asExpr() = stmtSequenceCfgNode }
1078+
1079+
/** Gets the underlying AST node as a `StmtSequence`. */
1080+
StmtSequence asStmtSequenceAstNode() { result = stmtSequenceCfgNode.getExpr() }
1081+
1082+
/** Gets the last statement in this sequence, if any. */
1083+
final ExprNode getLastStmt() { result.asExpr() = stmtSequenceCfgNode.getLastStmt() }
1084+
}
1085+
9871086
/**
9881087
* A data flow node corresponding to a method, block, or lambda expression.
9891088
*/

0 commit comments

Comments
 (0)