Skip to content

Commit 5e1faf8

Browse files
committed
Refactor using OptionalStep
1 parent 81f954a commit 5e1faf8

14 files changed

Lines changed: 117 additions & 43 deletions

File tree

rust/ql/integration-tests/hello-project/summary.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
| Macro calls - resolved | 2 |
1616
| Macro calls - total | 2 |
1717
| Macro calls - unresolved | 0 |
18-
| Taint edges - number of edges | 1675 |
18+
| Taint edges - number of edges | 1674 |
1919
| Taint reach - nodes tainted | 0 |
2020
| Taint reach - per million nodes | 0 |
2121
| Taint sinks - cryptographic operations | 0 |

rust/ql/integration-tests/hello-workspace/summary.cargo.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
| Macro calls - resolved | 2 |
1616
| Macro calls - total | 2 |
1717
| Macro calls - unresolved | 0 |
18-
| Taint edges - number of edges | 1675 |
18+
| Taint edges - number of edges | 1674 |
1919
| Taint reach - nodes tainted | 0 |
2020
| Taint reach - per million nodes | 0 |
2121
| Taint sinks - cryptographic operations | 0 |

rust/ql/integration-tests/hello-workspace/summary.rust-project.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
| Macro calls - resolved | 2 |
1616
| Macro calls - total | 2 |
1717
| Macro calls - unresolved | 0 |
18-
| Taint edges - number of edges | 1675 |
18+
| Taint edges - number of edges | 1674 |
1919
| Taint reach - nodes tainted | 0 |
2020
| Taint reach - per million nodes | 0 |
2121
| Taint sinks - cryptographic operations | 0 |

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,32 @@ final class SingletonContentSet extends ContentSet, TSingletonContentSet {
214214
override Content getAReadContent() { result = c }
215215
}
216216

217+
final class OptionalStep extends ContentSet, TOptionalStep {
218+
override string toString() {
219+
exists(string name |
220+
this = TOptionalStep(name) and
221+
result = "OptionalStep[" + name + "]"
222+
)
223+
}
224+
225+
override Content getAStoreContent() { none() }
226+
227+
override Content getAReadContent() { none() }
228+
}
229+
230+
final class OptionalBarrier extends ContentSet, TOptionalBarrier {
231+
override string toString() {
232+
exists(string name |
233+
this = TOptionalBarrier(name) and
234+
result = "OptionalBarrier[" + name + "]"
235+
)
236+
}
237+
238+
override Content getAStoreContent() { none() }
239+
240+
override Content getAReadContent() { none() }
241+
}
242+
217243
private import codeql.rust.internal.CachedStages
218244

219245
cached

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,12 @@ module RustDataFlow implements InputSig<Location> {
581581
model = ""
582582
or
583583
LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, model)
584+
or
585+
// Add flow through optional barriers. This step is then blocked by the barrier for queries that choose to use the barrier.
586+
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom
587+
.(Node::FlowSummaryNode)
588+
.getSummaryNode(), TOptionalBarrier(_), nodeTo.(Node::FlowSummaryNode).getSummaryNode()) and
589+
model = ""
584590
}
585591

586592
/**
@@ -710,7 +716,8 @@ module RustDataFlow implements InputSig<Location> {
710716
)
711717
or
712718
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), cs,
713-
node2.(FlowSummaryNode).getSummaryNode())
719+
node2.(FlowSummaryNode).getSummaryNode()) and
720+
not isSpecialContentSet(cs)
714721
}
715722

716723
pragma[nomagic]
@@ -807,7 +814,8 @@ module RustDataFlow implements InputSig<Location> {
807814
storeContentStep(node1, cs.(SingletonContentSet).getContent(), node2)
808815
or
809816
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), cs,
810-
node2.(FlowSummaryNode).getSummaryNode())
817+
node2.(FlowSummaryNode).getSummaryNode()) and
818+
not isSpecialContentSet(cs)
811819
}
812820

813821
/**
@@ -1093,7 +1101,24 @@ private module Cached {
10931101
newtype TReturnKind = TNormalReturnKind()
10941102

10951103
cached
1096-
newtype TContentSet = TSingletonContentSet(Content c)
1104+
newtype TContentSet =
1105+
TSingletonContentSet(Content c) or
1106+
TOptionalStep(string name) {
1107+
name = any(FlowSummaryImpl::Private::AccessPathToken tok).getAnArgument("OptionalStep")
1108+
} or
1109+
TOptionalBarrier(string name) {
1110+
name = any(FlowSummaryImpl::Private::AccessPathToken tok).getAnArgument("OptionalBarrier")
1111+
}
1112+
1113+
/**
1114+
* Holds if `cs` is used to encode a special operation as a content component, but should not
1115+
* be treated as an ordinary content component.
1116+
*/
1117+
cached
1118+
predicate isSpecialContentSet(ContentSet cs) {
1119+
cs instanceof TOptionalStep or
1120+
cs instanceof TOptionalBarrier
1121+
}
10971122

10981123
/** Holds if `n` is a flow source of kind `kind`. */
10991124
cached
@@ -1105,3 +1130,22 @@ private module Cached {
11051130
}
11061131

11071132
import Cached
1133+
1134+
cached
1135+
private module OptionalSteps {
1136+
cached
1137+
predicate optionalStep(Node node1, string name, Node node2) {
1138+
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(),
1139+
TOptionalStep(name), node2.(FlowSummaryNode).getSummaryNode()) or
1140+
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(),
1141+
TOptionalStep(name), node2.(FlowSummaryNode).getSummaryNode())
1142+
}
1143+
1144+
cached
1145+
predicate optionalBarrier(Node node, string name) {
1146+
FlowSummaryImpl::Private::Steps::summaryReadStep(_, TOptionalBarrier(name),
1147+
node.(FlowSummaryNode).getSummaryNode())
1148+
}
1149+
}
1150+
1151+
import OptionalSteps

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ module Input implements InputSig<Location, RustDataFlow> {
5454

5555
RustDataFlow::ArgumentPosition callbackSelfParameterPosition() { result.isClosureSelf() }
5656

57-
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() }
57+
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() and Stage::ref() }
5858

5959
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
6060

@@ -105,6 +105,10 @@ module Input implements InputSig<Location, RustDataFlow> {
105105
c = TFutureContent() and
106106
arg = ""
107107
)
108+
or
109+
cs = TOptionalStep(arg) and result = "OptionalStep"
110+
or
111+
cs = TOptionalBarrier(arg) and result = "OptionalBarrier"
108112
}
109113

110114
string encodeReturn(ReturnKind rk, string arg) { none() }
@@ -193,3 +197,12 @@ module ParsePositions {
193197
i = AccessPath::parseInt(c)
194198
}
195199
}
200+
201+
cached
202+
module Stage {
203+
cached
204+
predicate ref() { 1 = 1 }
205+
206+
cached
207+
predicate backref() { optionalStep(_, _, _) }
208+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
6969
exists(Content c | c = cs.(SingletonContentSet).getContent() |
7070
c instanceof ElementContent or
7171
c instanceof ReferenceContent
72-
)
72+
) and
73+
// Optional steps are added through isAdditionalFlowStep but we don't want the implicit reads
74+
not optionalStep(node, _, _)
7375
}
7476

7577
/**

rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,3 @@ private class StartswithCall extends Path::SafeAccessCheck::Range, CfgNodes::Met
2121
branch = true
2222
}
2323
}
24-
25-
/**
26-
* A call to `Path.canonicalize`.
27-
* See https://doc.rust-lang.org/std/path/struct.Path.html#method.canonicalize
28-
*/
29-
private class PathCanonicalizeCall extends Path::PathNormalization::Range {
30-
CfgNodes::MethodCallExprCfgNode call;
31-
32-
PathCanonicalizeCall() {
33-
call = this.asExpr() and
34-
call.getAstNode().(Resolvable).getResolvedPath() = "<crate::path::Path>::canonicalize"
35-
}
36-
37-
override DataFlow::Node getPathArg() { result.asExpr() = call.getReceiver() }
38-
}

rust/ql/lib/codeql/rust/frameworks/stdlib/fs.model.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ extensions:
1616
- ["lang:std", "<crate::path::PathBuf as crate::convert::From>::from", "Argument[0]", "ReturnValue", "taint", "manual"]
1717
- ["lang:std", "<crate::path::Path>::join", "Argument[self]", "ReturnValue", "taint", "manual"]
1818
- ["lang:std", "<crate::path::Path>::join", "Argument[0]", "ReturnValue", "taint", "manual"]
19+
- ["lang:std", "<crate::path::Path>::canonicalize", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].OptionalStep[normalize-path]", "taint", "manual"]
1920
- ["lang:std", "<crate::path::Path>::canonicalize", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]

rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,3 @@ extensions:
3232
- ["lang:alloc", "<crate::string::String>::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
3333
- ["lang:alloc", "<crate::string::String>::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
3434
- ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
35-
# Result
36-
- ["lang:core", "<crate::result::Result>::unwrap", "Argument[self]", "ReturnValue", "taint", "manual"]
37-

0 commit comments

Comments
 (0)