Skip to content

Commit 54de606

Browse files
committed
Rust: Disable dynamic dispatch when generating models
1 parent 28a7bd3 commit 54de606

File tree

3 files changed

+52
-25
lines changed

3 files changed

+52
-25
lines changed

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,11 @@ predicate indexAssignment(
286286
not index.getResolvedTarget().fromSource()
287287
}
288288

289-
module RustDataFlow implements InputSig<Location> {
289+
signature module RustDataFlowInputSig {
290+
predicate includeDynamicTargets();
291+
}
292+
293+
module RustDataFlowGen<RustDataFlowInputSig Input> implements InputSig<Location> {
290294
private import Aliases
291295
private import codeql.rust.dataflow.DataFlow
292296
private import Node as Node
@@ -441,7 +445,11 @@ module RustDataFlow implements InputSig<Location> {
441445
/** Gets a viable implementation of the target of the given `Call`. */
442446
DataFlowCallable viableCallable(DataFlowCall call) {
443447
exists(Call c | c = call.asCall() |
444-
result.asCfgScope() = c.getARuntimeTarget()
448+
(
449+
if Input::includeDynamicTargets()
450+
then result.asCfgScope() = c.getARuntimeTarget()
451+
else result.asCfgScope() = c.getStaticTarget()
452+
)
445453
or
446454
result.asSummarizedCallable() = getStaticTargetExt(c)
447455
)
@@ -890,6 +898,12 @@ module RustDataFlow implements InputSig<Location> {
890898
class DataFlowSecondLevelScope = Void;
891899
}
892900

901+
module RustDataFlowInput implements RustDataFlowInputSig {
902+
predicate includeDynamicTargets() { any() }
903+
}
904+
905+
module RustDataFlow = RustDataFlowGen<RustDataFlowInput>;
906+
893907
/** Provides logic related to captured variables. */
894908
module VariableCapture {
895909
private import codeql.rust.internal.CachedStages
@@ -1061,7 +1075,7 @@ private module Cached {
10611075
}
10621076

10631077
cached
1064-
newtype TParameterPosition =
1078+
newtype TParameterPositionImpl =
10651079
TPositionalParameterPosition(int i) {
10661080
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
10671081
or
@@ -1072,6 +1086,8 @@ private module Cached {
10721086
TClosureSelfParameterPosition() or
10731087
TSelfParameterPosition()
10741088

1089+
final class TParameterPosition = TParameterPositionImpl;
1090+
10751091
cached
10761092
newtype TReturnKind = TNormalReturnKind()
10771093

rust/ql/lib/codeql/rust/dataflow/internal/TaintTrackingImpl.qll

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
private import rust
2+
private import codeql.dataflow.DataFlow as DF
23
private import codeql.dataflow.TaintTracking
3-
private import codeql.rust.dataflow.DataFlow
4+
private import codeql.rust.dataflow.DataFlow as RustDataFlow
45
private import codeql.rust.dataflow.FlowSummary
5-
private import DataFlowImpl
6+
private import DataFlowImpl as DataFlowImpl
67
private import Node as Node
78
private import Content
89
private import FlowSummaryImpl as FlowSummaryImpl
@@ -29,7 +30,11 @@ private predicate excludedTaintStepContent(Content c) {
2930
)
3031
}
3132

32-
module RustTaintTracking implements InputSig<Location, RustDataFlow> {
33+
module RustTaintTrackingGen<DataFlowImpl::RustDataFlowInputSig I> implements
34+
InputSig<Location, DataFlowImpl::RustDataFlowGen<I>>
35+
{
36+
private module DataFlow = DataFlowImpl::RustDataFlowGen<I>;
37+
3338
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
3439

3540
/**
@@ -53,14 +58,14 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
5358
// is tainted and an operation reads from `foo` (e.g., `foo.bar`) then
5459
// taint is propagated.
5560
exists(Content c |
56-
RustDataFlow::readContentStep(pred, c, succ) and
61+
DataFlow::readContentStep(pred, c, succ) and
5762
not excludedTaintStepContent(c)
5863
)
5964
or
6065
// In addition to the above, for element and reference content we let
6166
// _all_ read steps (including those from flow summaries and those that
6267
// result in small primitive types) give rise to taint steps.
63-
exists(SingletonContentSet cs | RustDataFlow::readStep(pred, cs, succ) |
68+
exists(SingletonContentSet cs | DataFlow::readStep(pred, cs, succ) |
6469
cs.getContent() instanceof ElementContent
6570
or
6671
cs.getContent() instanceof ReferenceContent
@@ -79,9 +84,11 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
7984
)
8085
or
8186
succ.(Node::PostUpdateNode).getPreUpdateNode().asExpr() =
82-
getPostUpdateReverseStep(pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), false)
87+
DataFlowImpl::getPostUpdateReverseStep(pred.(Node::PostUpdateNode)
88+
.getPreUpdateNode()
89+
.asExpr(), false)
8390
or
84-
indexAssignment(any(CompoundAssignmentExpr cae),
91+
DataFlowImpl::indexAssignment(any(CompoundAssignmentExpr cae),
8592
pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), _, succ, _)
8693
)
8794
or
@@ -101,7 +108,7 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
101108
c instanceof ReferenceContent
102109
) and
103110
// Optional steps are added through isAdditionalFlowStep but we don't want the implicit reads
104-
not optionalStep(node, _, _)
111+
not DataFlowImpl::optionalStep(node, _, _)
105112
}
106113

107114
/**
@@ -110,3 +117,5 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
110117
*/
111118
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
112119
}
120+
121+
module RustTaintTracking = RustTaintTrackingGen<DataFlowImpl::RustDataFlowInput>;

rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import codeql.rust.dataflow.internal.Content
77
private import codeql.rust.dataflow.FlowSource as FlowSource
88
private import codeql.rust.dataflow.FlowSink as FlowSink
99
private import codeql.rust.dataflow.internal.TaintTrackingImpl
10+
private import codeql.rust.dataflow.internal.TaintTrackingImpl as TaintTrackingImpl
1011
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
1112
private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
1213

@@ -42,9 +43,15 @@ class QualifiedCallable extends TCallable {
4243
string getCanonicalPath() { result = path }
4344
}
4445

45-
module ModelGeneratorCommonInput implements
46-
ModelGeneratorCommonInputSig<R::Location, DataFlowImpl::RustDataFlow>
47-
{
46+
private module RustDataFlowInput implements DataFlowImpl::RustDataFlowInputSig {
47+
predicate includeDynamicTargets() { none() }
48+
}
49+
50+
module RustDataFlow = DataFlowImpl::RustDataFlowGen<RustDataFlowInput>;
51+
52+
module RustTaintTracking = TaintTrackingImpl::RustTaintTrackingGen<RustDataFlowInput>;
53+
54+
module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<R::Location, RustDataFlow> {
4855
// NOTE: We are not using type information for now.
4956
class Type = Unit;
5057

@@ -71,9 +78,8 @@ module ModelGeneratorCommonInput implements
7178

7279
string parameterExactAccess(R::ParamBase p) {
7380
result =
74-
"Argument[" +
75-
any(DataFlowImpl::RustDataFlow::ParameterPosition pos | p = pos.getParameterIn(_))
76-
.toString() + "]"
81+
"Argument[" + any(RustDataFlow::ParameterPosition pos | p = pos.getParameterIn(_)).toString() +
82+
"]"
7783
}
7884

7985
string parameterApproximateAccess(R::ParamBase p) { result = parameterExactAccess(p) }
@@ -83,16 +89,12 @@ module ModelGeneratorCommonInput implements
8389
}
8490

8591
bindingset[c]
86-
string paramReturnNodeAsApproximateOutput(
87-
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
88-
) {
92+
string paramReturnNodeAsApproximateOutput(QualifiedCallable c, RustDataFlow::ParameterPosition pos) {
8993
result = paramReturnNodeAsExactOutput(c, pos)
9094
}
9195

9296
bindingset[c]
93-
string paramReturnNodeAsExactOutput(
94-
QualifiedCallable c, DataFlowImpl::RustDataFlow::ParameterPosition pos
95-
) {
97+
string paramReturnNodeAsExactOutput(QualifiedCallable c, RustDataFlow::ParameterPosition pos) {
9698
result = parameterExactAccess(c.getFunction().getParam(pos.getPosition()))
9799
or
98100
pos.isSelf() and result = qualifierString()
@@ -102,7 +104,7 @@ module ModelGeneratorCommonInput implements
102104
result.getFunction() = ret.(Node::Node).getEnclosingCallable().asCfgScope()
103105
}
104106

105-
predicate isOwnInstanceAccessNode(DataFlowImpl::RustDataFlow::ReturnNode node) {
107+
predicate isOwnInstanceAccessNode(RustDataFlow::ReturnNode node) {
106108
// This is probably not relevant to implement for Rust, as we only use
107109
// `captureMixedFlow` which doesn't explicitly distinguish between
108110
// functions that return `self` and those that don't.
@@ -119,7 +121,7 @@ module ModelGeneratorCommonInput implements
119121
}
120122

121123
private import ModelGeneratorCommonInput
122-
private import MakeModelGeneratorFactory<R::Location, DataFlowImpl::RustDataFlow, RustTaintTracking, ModelGeneratorCommonInput>
124+
private import MakeModelGeneratorFactory<R::Location, RustDataFlow, RustTaintTracking, ModelGeneratorCommonInput>
123125

124126
private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
125127
class SummaryTargetApi extends QualifiedCallable {

0 commit comments

Comments
 (0)