Skip to content

Commit

Permalink
Merge pull request #18685 from paldepind/rust-future-content
Browse files Browse the repository at this point in the history
Rust: Basic support for future content and `.await`
  • Loading branch information
paldepind authored Feb 11, 2025
2 parents 7e569b4 + efb5b9b commit 5a49390
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 160 deletions.
19 changes: 18 additions & 1 deletion rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,15 @@ final class ElementContent extends Content, TElementContent {
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.
*
Expand Down Expand Up @@ -1194,6 +1203,12 @@ module RustDataFlow implements InputSig<Location> {
c instanceof FunctionCallReturnContent
)
or
exists(AwaitExprCfgNode await |
c instanceof FutureContent and
node1.asExpr() = await.getExpr() and
node2.asExpr() = await
)
or
VariableCapture::readStep(node1, c, node2)
)
or
Expand Down Expand Up @@ -1553,7 +1568,8 @@ private module Cached {
[
any(IndexExprCfgNode i).getBase(), any(FieldExprCfgNode access).getExpr(),
any(TryExprCfgNode try).getExpr(),
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr()
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(),
any(AwaitExprCfgNode a).getExpr()
]
} or
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
Expand Down Expand Up @@ -1609,6 +1625,7 @@ private module Cached {
// 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(),
Expand Down
4 changes: 4 additions & 0 deletions rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ module Input implements InputSig<Location, RustDataFlow> {
c = TTuplePositionContent(pos) and
arg = pos.toString()
)
or
result = "Future" and
c = TFutureContent() and
arg = ""
)
}

Expand Down
15 changes: 14 additions & 1 deletion rust/ql/test/library-tests/dataflow/models/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,17 @@ fn test_apply_flow_through() {
sink(t); // $ hasValueFlow=33
}

// has a flow model with value flow from argument to returned future
async fn get_async_number(a: i64) -> i64 {
37
}

async fn test_get_async_number() {
let s = source(46);
let t = get_async_number(s).await;
sink(t); // $ hasValueFlow=46
}

impl MyFieldEnum {
// has a source model
fn source(&self, i: i64) -> MyFieldEnum {
Expand Down Expand Up @@ -268,7 +279,8 @@ fn test_simple_sink() {
simple_sink(s); // $ hasValueFlow=17
}

fn main() {
#[tokio::main]
async fn main() {
test_identify();
test_get_var_pos();
test_set_var_pos();
Expand All @@ -286,5 +298,6 @@ fn main() {
test_enum_method_sink();
test_simple_source();
test_simple_sink();
test_get_async_number().await;
let dummy = Some(0); // ensure that the the `lang:core` crate is extracted
}
Loading

0 comments on commit 5a49390

Please sign in to comment.