Skip to content

Commit

Permalink
Rust: Flow through variants
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Nov 25, 2024
1 parent 2fb670a commit 5e7cd46
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 83 deletions.
36 changes: 32 additions & 4 deletions rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,37 @@ final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {

RecordExprCfgNode() { node = this.getRecordExpr() }

/** Gets the `i`th record expression. */
ExprCfgNode getExpr(int i) {
any(ChildMapping mapping)
.hasCfgChild(node, node.getRecordExprFieldList().getField(i).getExpr(), this, result)
/** Gets the record expression for the field `field`. */
pragma[nomagic]
ExprCfgNode getFieldExpr(string field) {
exists(RecordExprField ref |
ref = node.getRecordExprFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and
field = ref.getNameRef().getText()
)
}
}

/**
* A record pattern. For example:
* ```rust
* match x {
* Foo { a: 1, b: 2 } => "ok",
* Foo { .. } => "fail",
* }
* ```
*/
final class RecordPatCfgNode extends Nodes::RecordPatCfgNode {
private RecordPatChildMapping node;

RecordPatCfgNode() { node = this.getRecordPat() }

/** Gets the record pattern for the field `field`. */
PatCfgNode getFieldPat(string field) {
exists(RecordPatField rpf |
rpf = node.getRecordPatFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result) and
field = rpf.getNameRef().getText()
)
}
}
6 changes: 6 additions & 0 deletions rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class RecordExprChildMapping extends ParentAstNode, RecordExpr {
}
}

class RecordPatChildMapping extends ParentAstNode, RecordPat {
override predicate relevantChild(AstNode child) {
child = this.getRecordPatFieldList().getAField().getPat()
}
}

class FormatArgsExprChildMapping extends ParentAstNode, CfgImpl::ExprTrees::FormatArgsExprTree {
override predicate relevantChild(AstNode child) { child = this.getChildNode(_) }
}
Expand Down
6 changes: 6 additions & 0 deletions rust/ql/lib/codeql/rust/dataflow/DataFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ module DataFlow {

final class PostUpdateNode = Node::PostUpdateNode;

final class Content = DataFlowImpl::Content;

final class VariantContent = DataFlowImpl::VariantContent;

final class ContentSet = DataFlowImpl::ContentSet;

/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
Expand Down
Loading

0 comments on commit 5e7cd46

Please sign in to comment.