Skip to content

Commit 1f4e7d1

Browse files
committed
Rust: Handle arrays in taint tracking
1 parent 44239cb commit 1f4e7d1

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ private class StructFieldContent extends Content, TStructFieldContent {
626626
/**
627627
* Content stored at an element in an array.
628628
*/
629-
final private class ArrayElementContent extends VariantContent, TArrayElement {
629+
final class ArrayElementContent extends Content, TArrayElement {
630630
ArrayElementContent() { this = TArrayElement() }
631631

632632
override string toString() { result = "array[]" }
@@ -665,7 +665,7 @@ abstract class ContentSet extends TContentSet {
665665
abstract Content getAReadContent();
666666
}
667667

668-
final private class SingletonContentSet extends ContentSet, TSingletonContentSet {
668+
final class SingletonContentSet extends ContentSet, TSingletonContentSet {
669669
private Content c;
670670

671671
SingletonContentSet() { this = TSingletonContentSet(c) }

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
private import rust
22
private import codeql.dataflow.TaintTracking
33
private import codeql.rust.controlflow.CfgNodes
4-
private import DataFlowImpl
54
private import codeql.rust.dataflow.FlowSummary
6-
private import FlowSummaryImpl as FlowSummaryImpl
75
private import DataFlowImpl
6+
private import FlowSummaryImpl as FlowSummaryImpl
87

98
module RustTaintTracking implements InputSig<Location, RustDataFlow> {
109
predicate defaultTaintSanitizer(Node::Node node) { none() }
@@ -35,6 +34,15 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
3534
pred.asExpr() = index.getBase() and
3635
succ.asExpr() = index
3736
)
37+
or
38+
// Although data flow through collections is modeled using stores/reads,
39+
// we also allow taint to flow out of a tainted collection. This is
40+
// needed in order to support taint-tracking configurations where the
41+
// source is a collection.
42+
exists(ContentSet cs |
43+
RustDataFlow::readStep(pred, cs, succ) and
44+
cs.(SingletonContentSet).getContent() instanceof ArrayElementContent
45+
)
3846
)
3947
or
4048
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),
@@ -46,7 +54,10 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
4654
* and inputs to additional taint steps.
4755
*/
4856
bindingset[node]
49-
predicate defaultImplicitTaintRead(Node::Node node, ContentSet c) { none() }
57+
predicate defaultImplicitTaintRead(Node::Node node, ContentSet cs) {
58+
exists(node) and
59+
cs.(SingletonContentSet).getContent() instanceof ArrayElementContent
60+
}
5061

5162
/**
5263
* Holds if the additional step from `src` to `sink` should be considered in

rust/ql/test/library-tests/dataflow/taint/TaintFlowStep.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
| main.rs:23:13:23:13 | a | main.rs:23:13:23:19 | a as u8 | |
77
| main.rs:24:10:24:10 | b | main.rs:24:10:24:17 | b as i64 | |
88
| main.rs:38:23:38:23 | s | main.rs:38:23:38:29 | s[...] | |
9+
| main.rs:54:14:54:16 | arr | main.rs:54:14:54:19 | arr[1] | |
10+
| main.rs:64:24:64:24 | s | main.rs:64:24:64:27 | s[1] | |
11+
| main.rs:69:9:69:12 | arr2 | main.rs:69:9:69:15 | arr2[1] | |

rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,26 @@ edges
33
| main.rs:12:13:12:22 | source(...) | main.rs:13:10:13:14 | ... + ... | provenance | |
44
| main.rs:17:13:17:22 | source(...) | main.rs:18:10:18:11 | - ... | provenance | |
55
| main.rs:22:13:22:22 | source(...) | main.rs:24:10:24:17 | b as i64 | provenance | |
6+
| main.rs:53:19:53:28 | source(...) | main.rs:54:14:54:19 | arr[1] | provenance | |
7+
| main.rs:69:9:69:12 | [post] arr2 [array[]] | main.rs:70:14:70:17 | arr2 | provenance | |
8+
| main.rs:69:19:69:28 | source(...) | main.rs:69:9:69:12 | [post] arr2 [array[]] | provenance | |
69
nodes
710
| main.rs:12:13:12:22 | source(...) | semmle.label | source(...) |
811
| main.rs:13:10:13:14 | ... + ... | semmle.label | ... + ... |
912
| main.rs:17:13:17:22 | source(...) | semmle.label | source(...) |
1013
| main.rs:18:10:18:11 | - ... | semmle.label | - ... |
1114
| main.rs:22:13:22:22 | source(...) | semmle.label | source(...) |
1215
| main.rs:24:10:24:17 | b as i64 | semmle.label | b as i64 |
16+
| main.rs:53:19:53:28 | source(...) | semmle.label | source(...) |
17+
| main.rs:54:14:54:19 | arr[1] | semmle.label | arr[1] |
18+
| main.rs:69:9:69:12 | [post] arr2 [array[]] | semmle.label | [post] arr2 [array[]] |
19+
| main.rs:69:19:69:28 | source(...) | semmle.label | source(...) |
20+
| main.rs:70:14:70:17 | arr2 | semmle.label | arr2 |
1321
subpaths
1422
testFailures
1523
#select
1624
| main.rs:13:10:13:14 | ... + ... | main.rs:12:13:12:22 | source(...) | main.rs:13:10:13:14 | ... + ... | $@ | main.rs:12:13:12:22 | source(...) | source(...) |
1725
| main.rs:18:10:18:11 | - ... | main.rs:17:13:17:22 | source(...) | main.rs:18:10:18:11 | - ... | $@ | main.rs:17:13:17:22 | source(...) | source(...) |
1826
| main.rs:24:10:24:17 | b as i64 | main.rs:22:13:22:22 | source(...) | main.rs:24:10:24:17 | b as i64 | $@ | main.rs:22:13:22:22 | source(...) | source(...) |
27+
| main.rs:54:14:54:19 | arr[1] | main.rs:53:19:53:28 | source(...) | main.rs:54:14:54:19 | arr[1] | $@ | main.rs:53:19:53:28 | source(...) | source(...) |
28+
| main.rs:70:14:70:17 | arr2 | main.rs:69:19:69:28 | source(...) | main.rs:70:14:70:17 | arr2 | $@ | main.rs:69:19:69:28 | source(...) | source(...) |

rust/ql/test/library-tests/dataflow/taint/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ mod array_source {
5151

5252
pub fn array_tainted() {
5353
let arr = source(76);
54-
sink(arr[1]); // $ MISSING: hasTaintFlow=76
54+
sink(arr[1]); // $ hasTaintFlow=76
5555
}
5656
}
5757

@@ -67,7 +67,7 @@ mod array_sink {
6767
pub fn array_with_taint() {
6868
let mut arr2 = [1, 2, 3];
6969
arr2[1] = source(36);
70-
sink(arr2); // $ MISSING: hasTaintFlow=36
70+
sink(arr2); // $ hasTaintFlow=36
7171
}
7272
}
7373

0 commit comments

Comments
 (0)