Ruby: all Exprs have a corresponding DataFlow::Node that is more specific than just DataFlow::ExprNode

This commit is contained in:
Alex Ford
2023-02-24 16:29:13 +00:00
parent aac65b0df0
commit e948e22186
2 changed files with 129 additions and 1 deletions

View File

@@ -243,6 +243,35 @@ module ExprNodes {
override Literal getExpr() { result = super.getExpr() }
}
private class ControlExprChildMapping extends ExprChildMapping, ControlExpr {
override predicate relevantChild(AstNode n) { none() }
}
/** A control-flow node that wraps a `ControlExpr` AST expression. */
class ControlExprCfgNode extends ExprCfgNode {
override string getAPrimaryQlClass() { result = "ControlExprCfgNode" }
override ControlExprChildMapping e;
override ControlExpr getExpr() { result = super.getExpr() }
}
private class LhsExprChildMapping extends ExprChildMapping, LhsExpr {
override predicate relevantChild(AstNode n) { none() }
}
/** A control-flow node that wraps a `LhsExpr` AST expression. */
class LhsExprCfgNode extends ExprCfgNode {
override string getAPrimaryQlClass() { result = "LhsExprCfgNode" }
override LhsExprChildMapping e;
override LhsExpr getExpr() { result = super.getExpr() }
/** Gets a variable used in (or introduced by) this LHS. */
Variable getAVariable() { result = e.(VariableAccess).getVariable() }
}
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
}
@@ -256,7 +285,7 @@ module ExprNodes {
final override AssignExpr getExpr() { result = ExprCfgNode.super.getExpr() }
/** Gets the LHS of this assignment. */
final ExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) }
final LhsExprCfgNode getLhs() { e.hasCfgChild(e.getLeftOperand(), this, result) }
/** Gets the RHS of this assignment. */
final ExprCfgNode getRhs() { e.hasCfgChild(e.getRightOperand(), this, result) }

View File

@@ -984,6 +984,105 @@ class ClassNode extends ModuleNode {
ClassNode() { this.isClass() }
}
/**
* A data flow node corresponding to a literal expression.
*/
class LiteralNode extends ExprNode {
private CfgNodes::ExprNodes::LiteralCfgNode literalCfgNode;
LiteralNode() { this.asExpr() = literalCfgNode }
/** Gets the underlying AST node as a `Literal`. */
Literal asLiteralAstNode() { result = literalCfgNode.getExpr() }
}
/**
* A data flow node corresponding to an operation expression.
*/
class OperationNode extends ExprNode {
private CfgNodes::ExprNodes::OperationCfgNode operationCfgNode;
OperationNode() { this.asExpr() = operationCfgNode }
/** Gets the underlying AST node as an `Operation`. */
Operation asOperationAstNode() { result = operationCfgNode.getExpr() }
/** Gets the operator of this operation. */
final string getOperator() { result = operationCfgNode.getOperator() }
/** Gets an operand of this operation. */
final Node getAnOperand() { result.asExpr() = operationCfgNode.getAnOperand() }
}
/**
* A data flow node corresponding to a control expression (e.g. `if`, `while`, `for`).
*/
class ControlExprNode extends ExprNode {
private CfgNodes::ExprNodes::ControlExprCfgNode controlExprCfgNode;
ControlExprNode() { this.asExpr() = controlExprCfgNode }
/** Gets the underlying AST node as a `ControlExpr`. */
ControlExpr asControlExprAstNode() { result = controlExprCfgNode.getExpr() }
}
/**
* A data flow node corresponding to a variable access expression.
*/
class VariableAccessNode extends ExprNode {
private CfgNodes::ExprNodes::VariableAccessCfgNode variableAccessCfgNode;
VariableAccessNode() { this.asExpr() = variableAccessCfgNode }
/** Gets the underlying AST node as a `VariableAccess`. */
VariableAccess asVariableAccessAstNode() { result = variableAccessCfgNode.getExpr() }
}
/**
* A data flow node corresponding to a constant access expression.
*/
class ConstantAccessNode extends ExprNode {
private CfgNodes::ExprNodes::ConstantAccessCfgNode constantAccessCfgNode;
ConstantAccessNode() { this.asExpr() = constantAccessCfgNode }
/** Gets the underlying AST node as a `ConstantAccess`. */
ConstantAccess asConstantAccessAstNode() { result = constantAccessCfgNode.getExpr() }
/** Gets the node corresponding to the scope expression. */
final Node getScopeNode() { result.asExpr() = constantAccessCfgNode.getScopeExpr() }
}
/**
* A data flow node corresponding to a LHS expression.
*/
class LhsExprNode extends ExprNode {
private CfgNodes::ExprNodes::LhsExprCfgNode lhsExprCfgNode;
LhsExprNode() { this.asExpr() = lhsExprCfgNode }
/** Gets the underlying AST node as a `LhsExpr`. */
LhsExpr asLhsExprAstNode() { result = lhsExprCfgNode.getExpr() }
/** Gets a variable used in (or introduced by) this LHS. */
Variable getAVariable() { result = lhsExprCfgNode.getAVariable() }
}
/**
* A data flow node corresponding to a statement sequence expression.
*/
class StmtSequenceNode extends ExprNode {
private CfgNodes::ExprNodes::StmtSequenceCfgNode stmtSequenceCfgNode;
StmtSequenceNode() { this.asExpr() = stmtSequenceCfgNode }
/** Gets the underlying AST node as a `StmtSequence`. */
StmtSequence asStmtSequenceAstNode() { result = stmtSequenceCfgNode.getExpr() }
/** Gets the last statement in this sequence, if any. */
final ExprNode getLastStmt() { result.asExpr() = stmtSequenceCfgNode.getLastStmt() }
}
/**
* A data flow node corresponding to a method, block, or lambda expression.
*/