Merge pull request #19004 from paldepind/rust-data-flow-split

Rust: Extract data flow node and content into separate files
This commit is contained in:
Simon Friis Vindum
2025-03-17 07:02:35 +01:00
committed by GitHub
14 changed files with 807 additions and 762 deletions

View File

@@ -6,7 +6,8 @@
private import rust
private import codeql.dataflow.DataFlow
private import internal.DataFlowImpl as DataFlowImpl
private import DataFlowImpl::Node as Node
private import internal.Node as Node
private import internal.Content as Content
/**
* Provides classes for performing local (intra-procedural) and global
@@ -23,9 +24,23 @@ module DataFlow {
final class PostUpdateNode = Node::PostUpdateNodePublic;
final class Content = DataFlowImpl::Content;
final class Content = Content::Content;
final class ContentSet = DataFlowImpl::ContentSet;
final class FieldContent = Content::FieldContent;
final class TuplePositionContent = Content::TuplePositionContent;
final class TupleFieldContent = Content::TupleFieldContent;
final class RecordFieldContent = Content::RecordFieldContent;
final class ReferenceContent = Content::ReferenceContent;
final class ElementContent = Content::ElementContent;
final class FutureContent = Content::FutureContent;
final class ContentSet = Content::ContentSet;
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local

View File

@@ -0,0 +1,239 @@
/**
* Provides the `Content` class and subclasses thereof.
*/
private import rust
private import codeql.rust.controlflow.CfgNodes
private import DataFlowImpl
/**
* A path to a value contained in an object. For example a field name of a struct.
*/
abstract class Content extends TContent {
/** Gets a textual representation of this content. */
abstract string toString();
/** Gets the location of this content. */
abstract Location getLocation();
}
/** A field belonging to either a variant or a struct. */
abstract class FieldContent extends Content {
/** Gets an access to this field. */
pragma[nomagic]
abstract FieldExprCfgNode getAnAccess();
}
/** A tuple field belonging to either a variant or a struct. */
class TupleFieldContent extends FieldContent, TTupleFieldContent {
private TupleField field;
TupleFieldContent() { this = TTupleFieldContent(field) }
/** Holds if this field belongs to an enum variant. */
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
/** Holds if this field belongs to a struct. */
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() }
final override string toString() {
exists(Variant v, int pos, string vname |
this.isVariantField(v, pos) and
vname = v.getName().getText() and
// only print indices when the arity is > 1
if exists(v.getTupleField(1)) then result = vname + "(" + pos + ")" else result = vname
)
or
exists(Struct s, int pos, string sname |
this.isStructField(s, pos) and
sname = s.getName().getText() and
// only print indices when the arity is > 1
if exists(s.getTupleField(1)) then result = sname + "(" + pos + ")" else result = sname
)
}
final override Location getLocation() { result = field.getLocation() }
}
/** A record field belonging to either a variant or a struct. */
class RecordFieldContent extends FieldContent, TRecordFieldContent {
private RecordField field;
RecordFieldContent() { this = TRecordFieldContent(field) }
/** Holds if this field belongs to an enum variant. */
predicate isVariantField(Variant v, string name) { field.isVariantField(v, name) }
/** Holds if this field belongs to a struct. */
predicate isStructField(Struct s, string name) { field.isStructField(s, name) }
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getRecordField() }
final override string toString() {
exists(Variant v, string name, string vname |
this.isVariantField(v, name) and
vname = v.getName().getText() and
// only print field when the arity is > 1
if strictcount(v.getRecordField(_)) > 1 then result = vname + "." + name else result = vname
)
or
exists(Struct s, string name, string sname |
this.isStructField(s, name) and
sname = s.getName().getText() and
// only print field when the arity is > 1
if strictcount(s.getRecordField(_)) > 1 then result = sname + "." + name else result = sname
)
}
final override Location getLocation() { result = field.getLocation() }
}
/** A captured variable. */
final class CapturedVariableContent extends Content, TCapturedVariableContent {
private Variable v;
CapturedVariableContent() { this = TCapturedVariableContent(v) }
/** Gets the captured variable. */
Variable getVariable() { result = v }
override string toString() { result = "captured " + v }
override Location getLocation() { result = v.getLocation() }
}
/** A value referred to by a reference. */
final class ReferenceContent extends Content, TReferenceContent {
override string toString() { result = "&ref" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* An element in a collection where we do not track the specific collection
* type nor the placement of the element in the collection. Therefore the
* collection should be one where the elements are reasonably homogeneous,
* i.e., if one is tainted all elements are considered tainted.
*
* Examples include the elements of a set, array, vector, or stack.
*/
final class ElementContent extends Content, TElementContent {
override string toString() { result = "element" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* A value that a future resolves to.
*/
final class FutureContent extends Content, TFutureContent {
override string toString() { result = "future" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* Content stored at a position in a tuple.
*
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
* hence we don't store a canonical path for them.
*/
final class TuplePositionContent extends FieldContent, TTuplePositionContent {
private int pos;
TuplePositionContent() { this = TTuplePositionContent(pos) }
/** Gets the index of this tuple position. */
int getPosition() { result = pos }
override FieldExprCfgNode getAnAccess() {
// TODO: limit to tuple types
result.getNameRef().getText().toInt() = pos
}
override string toString() { result = "tuple." + pos.toString() }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* A content for the index of an argument to at function call.
*
* Used by the model generator to create flow summaries for higher-order
* functions.
*/
final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
private int pos;
FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
int getPosition() { result = pos }
override string toString() { result = "function argument at " + pos }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* A content for the return value of function call.
*
* Used by the model generator to create flow summaries for higher-order
* functions.
*/
final class FunctionCallReturnContent extends Content, TFunctionCallReturnContent {
override string toString() { result = "function return" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** A value that represents a set of `Content`s. */
abstract class ContentSet extends TContentSet {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets a content that may be stored into when storing into this set. */
abstract Content getAStoreContent();
/** Gets a content that may be read from when reading from this set. */
abstract Content getAReadContent();
}
final class SingletonContentSet extends ContentSet, TSingletonContentSet {
private Content c;
SingletonContentSet() { this = TSingletonContentSet(c) }
Content getContent() { result = c }
override string toString() { result = c.toString() }
override Content getAStoreContent() { result = c }
override Content getAReadContent() { result = c }
}
private import codeql.rust.internal.CachedStages
cached
newtype TContent =
TTupleFieldContent(TupleField field) { Stages::DataFlowStage::ref() } or
TRecordFieldContent(RecordField field) or
// TODO: Remove once library types are extracted
TVariantInLibTupleFieldContent(VariantInLib::VariantInLib v, int pos) { pos = v.getAPosition() } or
TElementContent() or
TFutureContent() or
TTuplePositionContent(int pos) {
pos in [0 .. max([
any(TuplePat pat).getNumberOfFields(),
any(FieldExpr access).getNameRef().getText().toInt()
]
)]
} or
TFunctionCallReturnContent() or
TFunctionCallArgumentContent(int pos) {
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
} or
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TReferenceContent()

View File

@@ -1,6 +1,7 @@
import codeql.rust.dataflow.DataFlow::DataFlow as DataFlow
private import rust
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.Node as Node
private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.dataflow.internal.DataFlowImplConsistency

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ private import codeql.dataflow.internal.FlowSummaryImpl
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.FlowSummary
private import Content
module Input implements InputSig<Location, RustDataFlow> {
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl

View File

@@ -0,0 +1,480 @@
/**
* Provides the `Node` class and subclasses thereof.
*
* Classes with names ending in `Public` are exposed as `final` aliases in the
* public `DataFlow` API, so they should not expose internal implementation details.
*/
private import codeql.util.Boolean
private import codeql.dataflow.DataFlow
private import codeql.dataflow.internal.DataFlowImpl
private import rust
private import SsaImpl as SsaImpl
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.dataflow.Ssa
private import codeql.rust.dataflow.FlowSummary
private import Node as Node
private import DataFlowImpl
private import FlowSummaryImpl as FlowSummaryImpl
/** An element, viewed as a node in a data flow graph. */
abstract class NodePublic extends TNode {
/** Gets the location of this node. */
abstract Location getLocation();
/** Gets a textual representation of this node. */
abstract string toString();
/**
* Gets the expression that corresponds to this node, if any.
*/
ExprCfgNode asExpr() { none() }
/**
* Gets the parameter that corresponds to this node, if any.
*/
ParamBase asParameter() { result = this.(SourceParameterNode).getParameter().getParamBase() }
/**
* Gets the pattern that corresponds to this node, if any.
*/
PatCfgNode asPat() { none() }
}
abstract class Node extends NodePublic {
/** Gets the enclosing callable. */
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
/** Do not call: use `getEnclosingCallable()` instead. */
abstract CfgScope getCfgScope();
/**
* Gets the control flow node that corresponds to this data flow node.
*/
CfgNode getCfgNode() { none() }
}
/** A node type that is not implemented. */
final class NaNode extends Node {
NaNode() { none() }
override CfgScope getCfgScope() { none() }
override string toString() { result = "N/A" }
override Location getLocation() { none() }
}
/** A data flow node used to model flow summaries. */
class FlowSummaryNode extends Node, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
/** Gets the summarized callable that this node belongs to, if any. */
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
/** Gets the AST source node that this node belongs to, if any */
FlowSummaryImpl::Public::SourceElement getSourceElement() {
result = this.getSummaryNode().getSourceElement()
}
/** Gets the AST sink node that this node belongs to, if any */
FlowSummaryImpl::Public::SinkElement getSinkElement() {
result = this.getSummaryNode().getSinkElement()
}
/** Holds is this node is a source node of kind `kind`. */
predicate isSource(string kind, string model) {
this.getSummaryNode().(FlowSummaryImpl::Private::SourceOutputNode).isEntry(kind, model)
}
/** Holds is this node is a sink node of kind `kind`. */
predicate isSink(string kind, string model) {
this.getSummaryNode().(FlowSummaryImpl::Private::SinkInputNode).isExit(kind, model)
}
override CfgScope getCfgScope() {
result = this.getSummaryNode().getSourceElement().getEnclosingCfgScope()
or
result = this.getSummaryNode().getSinkElement().getEnclosingCfgScope()
}
override DataFlowCallable getEnclosingCallable() {
result.asLibraryCallable() = this.getSummarizedCallable()
or
result.asCfgScope() = this.getCfgScope()
}
override Location getLocation() {
exists(this.getSummarizedCallable()) and
result instanceof EmptyLocation
or
result = this.getSourceElement().getLocation()
or
result = this.getSinkElement().getLocation()
}
override string toString() { result = this.getSummaryNode().toString() }
}
/** A data flow node that corresponds directly to a CFG node for an AST node. */
abstract class AstCfgFlowNode extends Node {
AstCfgNode n;
final override CfgNode getCfgNode() { result = n }
final override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
final override Location getLocation() { result = n.getAstNode().getLocation() }
final override string toString() { result = n.getAstNode().toString() }
}
/**
* A node in the data flow graph that corresponds to an expression in the
* AST.
*
* Note that because of control flow splitting, one `Expr` may correspond
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
class ExprNode extends AstCfgFlowNode, TExprNode {
override ExprCfgNode n;
ExprNode() { this = TExprNode(n) }
override ExprCfgNode asExpr() { result = n }
}
final class PatNode extends AstCfgFlowNode, TPatNode {
override PatCfgNode n;
PatNode() { this = TPatNode(n) }
override PatCfgNode asPat() { result = n }
}
/** A data flow node that corresponds to a name node in the CFG. */
final class NameNode extends AstCfgFlowNode, TNameNode {
override NameCfgNode n;
NameNode() { this = TNameNode(n) }
NameCfgNode asName() { result = n }
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
abstract class ParameterNode extends Node {
/** Holds if this node is a parameter of `c` at position `pos`. */
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
}
final class SourceParameterNode extends AstCfgFlowNode, ParameterNode, TSourceParameterNode {
override ParamBaseCfgNode n;
SourceParameterNode() { this = TSourceParameterNode(n) }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
n.getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
}
/** Get the parameter position of this parameter. */
ParameterPosition getPosition() { this.isParameterOf(_, result) }
/** Gets the parameter in the CFG that this node corresponds to. */
ParamBaseCfgNode getParameter() { result = n }
}
/** A parameter for a library callable with a flow summary. */
final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
private ParameterPosition pos_;
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
}
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.getSummarizedCallable() = c.asLibraryCallable() and pos = pos_
}
}
/**
* The run-time representation of a closure itself at function entry, viewed
* as a node in a data flow graph.
*/
final class ClosureParameterNode extends ParameterNode, TClosureSelfReferenceNode {
private CfgScope cfgScope;
ClosureParameterNode() { this = TClosureSelfReferenceNode(cfgScope) }
final override CfgScope getCfgScope() { result = cfgScope }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
cfgScope = c.asCfgScope() and pos.isClosureSelf()
}
override Location getLocation() { result = cfgScope.getLocation() }
override string toString() { result = "closure self in " + cfgScope }
}
abstract class ArgumentNode extends Node {
abstract predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos);
}
final class ExprArgumentNode extends ArgumentNode, ExprNode {
private CallExprBaseCfgNode call_;
private RustDataFlow::ArgumentPosition pos_;
ExprArgumentNode() { isArgumentForCall(n, call_, pos_) }
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
call.asCallBaseExprCfgNode() = call_ and pos = pos_
}
}
/**
* The receiver of a method call _after_ any implicit borrow or dereferencing
* has taken place.
*/
final class ReceiverNode extends ArgumentNode, TReceiverNode {
private MethodCallExprCfgNode n;
ReceiverNode() { this = TReceiverNode(n, false) }
ExprCfgNode getReceiver() { result = n.getReceiver() }
MethodCallExprCfgNode getMethodCall() { result = n }
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
call.asMethodCallExprCfgNode() = n and pos = TSelfParameterPosition()
}
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
override Location getLocation() { result = this.getReceiver().getLocation() }
override string toString() { result = "receiver for " + this.getReceiver() }
}
final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
private FlowSummaryImpl::Private::SummaryNode receiver;
private RustDataFlow::ArgumentPosition pos_;
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(receiver, this.getSummaryNode(), pos_)
}
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
call.isSummaryCall(_, receiver) and pos = pos_
}
}
/**
* A data flow node that represents the run-time representation of a closure
* passed into the closure body at an invocation.
*/
final class ClosureArgumentNode extends ArgumentNode, ExprNode {
private CallExprCfgNode call_;
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
call.asCallExprCfgNode() = call_ and
pos.isClosureSelf()
}
}
/** An SSA node. */
class SsaNode extends Node, TSsaNode {
SsaImpl::DataFlowIntegration::SsaNode node;
SsaNode() { this = TSsaNode(node) }
override CfgScope getCfgScope() { result = node.getBasicBlock().getScope() }
/** Gets the definition this node corresponds to, if any. */
SsaImpl::Definition asDefinition() {
result = node.(SsaImpl::DataFlowIntegration::SsaDefinitionNode).getDefinition()
}
override Location getLocation() { result = node.getLocation() }
override string toString() { result = "[SSA] " + node.toString() }
}
/** A data flow node that represents a value returned by a callable. */
abstract class ReturnNode extends Node {
abstract ReturnKind getKind();
}
final class ExprReturnNode extends ExprNode, ReturnNode {
ExprReturnNode() { this.getCfgNode().getASuccessor() instanceof AnnotatedExitCfgNode }
override ReturnKind getKind() { result = TNormalReturnKind() }
}
final class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
override ReturnKind getKind() { result = rk }
}
/** A data flow node that represents the output of a call. */
abstract class OutNode extends Node {
/** Gets the underlying call for this node. */
abstract DataFlowCall getCall(ReturnKind kind);
}
final private class ExprOutNode extends ExprNode, OutNode {
ExprOutNode() { this.asExpr() instanceof CallExprBaseCfgNode }
/** Gets the underlying call CFG node that includes this out node. */
override DataFlowCall getCall(ReturnKind kind) {
result.asCallBaseExprCfgNode() = this.getCfgNode() and
kind = TNormalReturnKind()
}
}
final class SummaryOutNode extends FlowSummaryNode, OutNode {
private DataFlowCall call;
private ReturnKind kind_;
SummaryOutNode() {
exists(FlowSummaryImpl::Private::SummaryNode receiver |
call.isSummaryCall(_, receiver) and
FlowSummaryImpl::Private::summaryOutNode(receiver, this.getSummaryNode(), kind_)
)
}
override DataFlowCall getCall(ReturnKind kind) { result = call and kind = kind_ }
}
/**
* A synthesized data flow node representing a closure object that tracks
* captured variables.
*/
class CaptureNode extends Node, TCaptureNode {
private VariableCapture::Flow::SynthesizedCaptureNode cn;
CaptureNode() { this = TCaptureNode(cn) }
VariableCapture::Flow::SynthesizedCaptureNode getSynthesizedCaptureNode() { result = cn }
override CfgScope getCfgScope() { result = cn.getEnclosingCallable() }
override Location getLocation() { result = cn.getLocation() }
override string toString() { result = cn.toString() }
}
/**
* A node associated with an object after an operation that might have
* changed its state.
*
* This can be either the argument to a callable after the callable returns
* (which might have mutated the argument), or the qualifier of a field after
* an update to the field.
*
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
* to the value before the update.
*/
abstract class PostUpdateNodePublic extends NodePublic {
/** Gets the node before the state update. */
abstract NodePublic getPreUpdateNode();
}
abstract class PostUpdateNode extends PostUpdateNodePublic, Node {
override string toString() { result = "[post] " + this.getPreUpdateNode().toString() }
}
final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
private ExprCfgNode n;
ExprPostUpdateNode() { this = TExprPostUpdateNode(n) }
override Node getPreUpdateNode() { result = TExprNode(n) }
override CfgScope getCfgScope() { result = n.getScope() }
override Location getLocation() { result = n.getLocation() }
}
final class ReceiverPostUpdateNode extends PostUpdateNode, TReceiverNode {
private MethodCallExprCfgNode n;
ReceiverPostUpdateNode() { this = TReceiverNode(n, true) }
override Node getPreUpdateNode() { result = TReceiverNode(n, false) }
override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() }
override Location getLocation() { result = n.getReceiver().getLocation() }
}
final class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryNode pre;
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
final override string toString() { result = PostUpdateNode.super.toString() }
}
private class CapturePostUpdateNode extends PostUpdateNode, CaptureNode {
private CaptureNode pre;
CapturePostUpdateNode() {
VariableCapture::Flow::capturePostUpdateNode(this.getSynthesizedCaptureNode(),
pre.getSynthesizedCaptureNode())
}
override Node getPreUpdateNode() { result = pre }
final override string toString() { result = PostUpdateNode.super.toString() }
}
final class CastNode = NaNode;
private import codeql.rust.internal.CachedStages
cached
newtype TNode =
TExprNode(ExprCfgNode n) { Stages::DataFlowStage::ref() } or
TSourceParameterNode(ParamBaseCfgNode p) or
TPatNode(PatCfgNode p) or
TNameNode(NameCfgNode n) { n.getName() = any(Variable v).getName() } or
TExprPostUpdateNode(ExprCfgNode e) {
isArgumentForCall(e, _, _)
or
lambdaCallExpr(_, _, e)
or
lambdaCreationExpr(e.getExpr(), _)
or
// Whenever `&mut e` has a post-update node we also create one for `e`.
// E.g., for `e` in `f(..., &mut e, ...)` or `*(&mut e) = ...`.
e = any(RefExprCfgNode ref | ref.isMut() and exists(TExprPostUpdateNode(ref))).getExpr()
or
e =
[
any(IndexExprCfgNode i).getBase(), any(FieldExprCfgNode access).getExpr(),
any(TryExprCfgNode try).getExpr(),
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(),
any(AwaitExprCfgNode a).getExpr(), any(MethodCallExprCfgNode mc).getReceiver()
]
} or
TReceiverNode(MethodCallExprCfgNode mc, Boolean isPost) or
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TClosureSelfReferenceNode(CfgScope c) { lambdaCreationExpr(c, _) } or
TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn)

View File

@@ -4,6 +4,8 @@ private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSummary
private import DataFlowImpl
private import Node as Node
private import Content
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.rust.internal.CachedStages

View File

@@ -131,6 +131,8 @@ module Stages {
cached
module DataFlowStage {
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.Node
private import codeql.rust.dataflow.internal.Content
private import codeql.rust.dataflow.internal.TaintTrackingImpl
/**
@@ -152,6 +154,10 @@ module Stages {
exists(Node n)
or
RustTaintTracking::defaultAdditionalTaintStep(_, _, _)
or
exists(DataFlowCall call)
or
exists(Content content)
}
}
}

View File

@@ -14,7 +14,7 @@ private import codeql.rust.security.SensitiveData
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSource
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.Node as Node
/**
* Provides default sources, sinks and sanitizers for detecting "use of a broken or weak

View File

@@ -8,6 +8,7 @@ private import codeql.dataflow.test.InlineFlowTest
private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.Node as Node
private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.rust.dataflow.internal.ModelsAsData as MaD
private import internal.InlineExpectationsTestImpl as InlineExpectationsTestImpl

View File

@@ -17,7 +17,6 @@ import rust
import codeql.rust.security.CleartextLoggingExtensions
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.dataflow.internal.DataFlowImpl
/**
* A taint-tracking configuration for cleartext logging vulnerabilities.
@@ -44,7 +43,7 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
// flow out from tuple content at sinks.
isSink(node) and
c.getAReadContent() instanceof TuplePositionContent
c.getAReadContent() instanceof DataFlow::TuplePositionContent
}
}

View File

@@ -3,6 +3,8 @@ private import rust
private import rust as R
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.Node as Node
private import codeql.rust.dataflow.internal.Content
private import codeql.rust.dataflow.FlowSource as FlowSource
private import codeql.rust.dataflow.FlowSink as FlowSink
private import codeql.rust.dataflow.internal.TaintTrackingImpl

View File

@@ -8,7 +8,7 @@ private module Tm = TranslateModels<provenance/1>;
query predicate models = Tm::models/2;
query predicate localStep(Node nodeFrom, Node nodeTo) {
query predicate localStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Local flow steps that don't originate from a flow summary.
RustDataFlow::simpleLocalFlowStep(nodeFrom, nodeTo, "")
}

View File

@@ -1,5 +1,5 @@
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.internal.DataFlowImpl
import codeql.rust.dataflow.internal.Node as Node
import codeql.rust.dataflow.internal.TaintTrackingImpl
import utils.test.TranslateModels