Skip to content

Commit 5a49390

Browse files
authored
Merge pull request github#18685 from paldepind/rust-future-content
Rust: Basic support for future content and `.await`
2 parents 7e569b4 + efb5b9b commit 5a49390

File tree

6 files changed

+226
-160
lines changed

6 files changed

+226
-160
lines changed

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,15 @@ final class ElementContent extends Content, TElementContent {
843843
override Location getLocation() { result instanceof EmptyLocation }
844844
}
845845

846+
/**
847+
* A value that a future resolves to.
848+
*/
849+
final class FutureContent extends Content, TFutureContent {
850+
override string toString() { result = "future" }
851+
852+
override Location getLocation() { result instanceof EmptyLocation }
853+
}
854+
846855
/**
847856
* Content stored at a position in a tuple.
848857
*
@@ -1194,6 +1203,12 @@ module RustDataFlow implements InputSig<Location> {
11941203
c instanceof FunctionCallReturnContent
11951204
)
11961205
or
1206+
exists(AwaitExprCfgNode await |
1207+
c instanceof FutureContent and
1208+
node1.asExpr() = await.getExpr() and
1209+
node2.asExpr() = await
1210+
)
1211+
or
11971212
VariableCapture::readStep(node1, c, node2)
11981213
)
11991214
or
@@ -1553,7 +1568,8 @@ private module Cached {
15531568
[
15541569
any(IndexExprCfgNode i).getBase(), any(FieldExprCfgNode access).getExpr(),
15551570
any(TryExprCfgNode try).getExpr(),
1556-
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr()
1571+
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(),
1572+
any(AwaitExprCfgNode a).getExpr()
15571573
]
15581574
} or
15591575
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
@@ -1609,6 +1625,7 @@ private module Cached {
16091625
// TODO: Remove once library types are extracted
16101626
TVariantInLibTupleFieldContent(VariantInLib::VariantInLib v, int pos) { pos = v.getAPosition() } or
16111627
TElementContent() or
1628+
TFutureContent() or
16121629
TTuplePositionContent(int pos) {
16131630
pos in [0 .. max([
16141631
any(TuplePat pat).getNumberOfFields(),

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ module Input implements InputSig<Location, RustDataFlow> {
102102
c = TTuplePositionContent(pos) and
103103
arg = pos.toString()
104104
)
105+
or
106+
result = "Future" and
107+
c = TFutureContent() and
108+
arg = ""
105109
)
106110
}
107111

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ fn test_apply_flow_through() {
203203
sink(t); // $ hasValueFlow=33
204204
}
205205

206+
// has a flow model with value flow from argument to returned future
207+
async fn get_async_number(a: i64) -> i64 {
208+
37
209+
}
210+
211+
async fn test_get_async_number() {
212+
let s = source(46);
213+
let t = get_async_number(s).await;
214+
sink(t); // $ hasValueFlow=46
215+
}
216+
206217
impl MyFieldEnum {
207218
// has a source model
208219
fn source(&self, i: i64) -> MyFieldEnum {
@@ -268,7 +279,8 @@ fn test_simple_sink() {
268279
simple_sink(s); // $ hasValueFlow=17
269280
}
270281

271-
fn main() {
282+
#[tokio::main]
283+
async fn main() {
272284
test_identify();
273285
test_get_var_pos();
274286
test_set_var_pos();
@@ -286,5 +298,6 @@ fn main() {
286298
test_enum_method_sink();
287299
test_simple_source();
288300
test_simple_sink();
301+
test_get_async_number().await;
289302
let dummy = Some(0); // ensure that the the `lang:core` crate is extracted
290303
}

0 commit comments

Comments
 (0)