Skip to content

Commit 71f86d2

Browse files
committed
Rust: Add reverse post-update flow steps
1 parent fba276a commit 71f86d2

6 files changed

Lines changed: 49 additions & 6 deletions

File tree

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ private ExprCfgNode getALastEvalNode(ExprCfgNode e) {
197197
result.(BreakExprCfgNode).getTarget() = e
198198
}
199199

200+
ExprCfgNode getPostUpdateReverseStep(ExprCfgNode e, boolean preservesValue) {
201+
result = getALastEvalNode(e) and
202+
preservesValue = true
203+
or
204+
result = e.(CastExprCfgNode).getExpr() and
205+
preservesValue = false
206+
}
207+
200208
module LocalFlow {
201209
predicate flowSummaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
202210
exists(FlowSummaryImpl::Public::SummarizedCallable c |
@@ -258,6 +266,9 @@ module LocalFlow {
258266
// The dual step of the above, for the post-update nodes.
259267
nodeFrom.(PostUpdateNode).getPreUpdateNode().(ReceiverNode).getReceiver() =
260268
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr()
269+
or
270+
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr() =
271+
getPostUpdateReverseStep(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr(), true)
261272
}
262273
}
263274

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,11 @@ newtype TNode =
472472
any(PrefixExprCfgNode pe | pe.getOperatorName() = "*").getExpr(),
473473
any(AwaitExprCfgNode a).getExpr(), any(MethodCallExprCfgNode mc).getReceiver()
474474
]
475+
or
476+
exists(ExprCfgNode pred |
477+
exists(TExprPostUpdateNode(pred)) and
478+
e = getPostUpdateReverseStep(pred, _)
479+
)
475480
} or
476481
TReceiverNode(MethodCallExprCfgNode mc, Boolean isPost) or
477482
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ import Cached
332332
private import codeql.rust.dataflow.Ssa
333333

334334
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
335+
private import codeql.rust.dataflow.internal.DataFlowImpl as DataFlowImpl
336+
335337
class Expr extends CfgNodes::AstCfgNode {
336338
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
337339
}
@@ -343,14 +345,22 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
343345
none() // handled in `DataFlowImpl.qll` instead
344346
}
345347

348+
private predicate isArg(CfgNodes::CallExprBaseCfgNode call, CfgNodes::ExprCfgNode e) {
349+
call.getArgument(_) = e
350+
or
351+
call.(CfgNodes::MethodCallExprCfgNode).getReceiver() = e
352+
or
353+
exists(CfgNodes::ExprCfgNode mid |
354+
isArg(call, mid) and
355+
e = DataFlowImpl::getPostUpdateReverseStep(mid, _)
356+
)
357+
}
358+
346359
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
347360
exists(CfgNodes::CallExprBaseCfgNode call, Variable v, BasicBlock bb, int i |
348361
def.definesAt(v, bb, i) and
349-
mutablyBorrows(bb.getNode(i).getAstNode(), v)
350-
|
351-
call.getArgument(_) = bb.getNode(i)
352-
or
353-
call.(CfgNodes::MethodCallExprCfgNode).getReceiver() = bb.getNode(i)
362+
mutablyBorrows(bb.getNode(i).getAstNode(), v) and
363+
isArg(call, bb.getNode(i))
354364
)
355365
}
356366

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
5353
exists(FormatArgsExprCfgNode format | succ.asExpr() = format |
5454
pred.asExpr() = [format.getArgumentExpr(_), format.getFormatTemplateVariableAccess(_)]
5555
)
56+
or
57+
succ.(Node::PostUpdateNode).getPreUpdateNode().asExpr() =
58+
getPostUpdateReverseStep(pred.(Node::PostUpdateNode).getPreUpdateNode().asExpr(), false)
5659
)
5760
or
5861
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(Node::FlowSummaryNode).getSummaryNode(),

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ edges
1818
| main.rs:38:23:38:31 | source(...) | main.rs:38:6:38:11 | [post] &mut a [&ref, MyStruct] | provenance | |
1919
| main.rs:39:10:39:10 | a [MyStruct] | main.rs:30:17:30:21 | SelfParam [&ref, MyStruct] | provenance | |
2020
| main.rs:39:10:39:10 | a [MyStruct] | main.rs:39:10:39:21 | a.get_data(...) | provenance | |
21+
| main.rs:44:12:44:17 | [post] &mut a [&ref, MyStruct] | main.rs:44:17:44:17 | [post] a [MyStruct] | provenance | |
22+
| main.rs:44:17:44:17 | [post] a [MyStruct] | main.rs:45:10:45:10 | a [MyStruct] | provenance | |
23+
| main.rs:44:30:44:38 | source(...) | main.rs:26:28:26:33 | ...: i64 | provenance | |
24+
| main.rs:44:30:44:38 | source(...) | main.rs:44:12:44:17 | [post] &mut a [&ref, MyStruct] | provenance | |
25+
| main.rs:45:10:45:10 | a [MyStruct] | main.rs:30:17:30:21 | SelfParam [&ref, MyStruct] | provenance | |
26+
| main.rs:45:10:45:10 | a [MyStruct] | main.rs:45:10:45:21 | a.get_data(...) | provenance | |
2127
| main.rs:48:12:48:17 | ...: i64 | main.rs:49:10:49:10 | n | provenance | |
2228
| main.rs:53:9:53:9 | a | main.rs:54:13:54:13 | a | provenance | |
2329
| main.rs:53:13:53:21 | source(...) | main.rs:53:9:53:9 | a | provenance | |
@@ -110,6 +116,11 @@ nodes
110116
| main.rs:38:23:38:31 | source(...) | semmle.label | source(...) |
111117
| main.rs:39:10:39:10 | a [MyStruct] | semmle.label | a [MyStruct] |
112118
| main.rs:39:10:39:21 | a.get_data(...) | semmle.label | a.get_data(...) |
119+
| main.rs:44:12:44:17 | [post] &mut a [&ref, MyStruct] | semmle.label | [post] &mut a [&ref, MyStruct] |
120+
| main.rs:44:17:44:17 | [post] a [MyStruct] | semmle.label | [post] a [MyStruct] |
121+
| main.rs:44:30:44:38 | source(...) | semmle.label | source(...) |
122+
| main.rs:45:10:45:10 | a [MyStruct] | semmle.label | a [MyStruct] |
123+
| main.rs:45:10:45:21 | a.get_data(...) | semmle.label | a.get_data(...) |
113124
| main.rs:48:12:48:17 | ...: i64 | semmle.label | ...: i64 |
114125
| main.rs:49:10:49:10 | n | semmle.label | n |
115126
| main.rs:53:9:53:9 | a | semmle.label | a |
@@ -194,6 +205,8 @@ nodes
194205
subpaths
195206
| main.rs:38:23:38:31 | source(...) | main.rs:26:28:26:33 | ...: i64 | main.rs:26:17:26:25 | SelfParam [Return] [&ref, MyStruct] | main.rs:38:6:38:11 | [post] &mut a [&ref, MyStruct] |
196207
| main.rs:39:10:39:10 | a [MyStruct] | main.rs:30:17:30:21 | SelfParam [&ref, MyStruct] | main.rs:30:31:32:5 | { ... } | main.rs:39:10:39:21 | a.get_data(...) |
208+
| main.rs:44:30:44:38 | source(...) | main.rs:26:28:26:33 | ...: i64 | main.rs:26:17:26:25 | SelfParam [Return] [&ref, MyStruct] | main.rs:44:12:44:17 | [post] &mut a [&ref, MyStruct] |
209+
| main.rs:45:10:45:10 | a [MyStruct] | main.rs:30:17:30:21 | SelfParam [&ref, MyStruct] | main.rs:30:31:32:5 | { ... } | main.rs:45:10:45:21 | a.get_data(...) |
197210
| main.rs:63:26:63:26 | a | main.rs:57:17:57:22 | ...: i64 | main.rs:57:32:59:1 | { ... } | main.rs:63:13:63:27 | pass_through(...) |
198211
| main.rs:68:26:71:5 | { ... } | main.rs:57:17:57:22 | ...: i64 | main.rs:57:32:59:1 | { ... } | main.rs:68:13:71:6 | pass_through(...) |
199212
| main.rs:82:26:82:26 | a | main.rs:78:21:78:26 | ...: i64 | main.rs:78:36:80:5 | { ... } | main.rs:82:13:82:27 | pass_through(...) |
@@ -205,6 +218,7 @@ testFailures
205218
#select
206219
| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) | source(...) |
207220
| main.rs:39:10:39:21 | a.get_data(...) | main.rs:38:23:38:31 | source(...) | main.rs:39:10:39:21 | a.get_data(...) | $@ | main.rs:38:23:38:31 | source(...) | source(...) |
221+
| main.rs:45:10:45:21 | a.get_data(...) | main.rs:44:30:44:38 | source(...) | main.rs:45:10:45:21 | a.get_data(...) | $@ | main.rs:44:30:44:38 | source(...) | source(...) |
208222
| main.rs:49:10:49:10 | n | main.rs:53:13:53:21 | source(...) | main.rs:49:10:49:10 | n | $@ | main.rs:53:13:53:21 | source(...) | source(...) |
209223
| main.rs:64:10:64:10 | b | main.rs:62:13:62:21 | source(...) | main.rs:64:10:64:10 | b | $@ | main.rs:62:13:62:21 | source(...) | source(...) |
210224
| main.rs:72:10:72:10 | a | main.rs:70:9:70:18 | source(...) | main.rs:72:10:72:10 | a | $@ | main.rs:70:9:70:18 | source(...) | source(...) |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn data_out_of_call_side_effect1() {
4242
fn data_out_of_call_side_effect2() {
4343
let mut a = MyStruct { data: 0 };
4444
({ 42; &mut a}).set_data(source(9));
45-
sink(a.get_data()); // $ MISSING: hasValueFlow=9
45+
sink(a.get_data()); // $ hasValueFlow=9
4646
}
4747

4848
fn data_in(n: i64) {

0 commit comments

Comments
 (0)