Skip to content

Commit 5a5679b

Browse files
committed
Rust: Taint flow through operations using MaD
1 parent 4191664 commit 5a5679b

File tree

21 files changed

+438
-204
lines changed

21 files changed

+438
-204
lines changed

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,11 @@ module LocalFlow {
204204
)
205205
or
206206
// An edge from a pattern/expression to its corresponding SSA definition.
207-
nodeFrom.(AstNodeNode).getAstNode() =
208-
nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess()
207+
exists(AstNode n |
208+
n = nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
209+
n = nodeFrom.(AstNodeNode).getAstNode() and
210+
not n = any(CompoundAssignmentExpr cae).getLhs()
211+
)
209212
or
210213
nodeFrom.(SourceParameterNode).getParameter().(Param).getPat() = nodeTo.asPat()
211214
or
@@ -422,13 +425,23 @@ module RustDataFlow implements InputSig<Location> {
422425

423426
final class ReturnKind = ReturnKindAlias;
424427

428+
private Function getStaticTargetExt(Call c) {
429+
result = c.getStaticTarget()
430+
or
431+
not exists(c.getStaticTarget()) and
432+
exists(TraitItemNode t, string methodName |
433+
c.(Operation).isOverloaded(t, methodName, _) and
434+
result = t.getAssocItem(methodName)
435+
)
436+
}
437+
425438
/** Gets a viable implementation of the target of the given `Call`. */
426439
DataFlowCallable viableCallable(DataFlowCall call) {
427440
exists(Call c | c = call.asCall() |
428441
result.asCfgScope() = c.getARuntimeTarget()
429442
or
430443
exists(SummarizedCallable sc, Function staticTarget |
431-
staticTarget = c.getStaticTarget() and
444+
staticTarget = getStaticTargetExt(c) and
432445
sc = result.asSummarizedCallable()
433446
|
434447
sc = staticTarget
@@ -625,8 +638,18 @@ module RustDataFlow implements InputSig<Location> {
625638
implicitDeref(node1, node2, c)
626639
or
627640
// A read step dual to the store step for implicit borrows.
628-
implicitBorrow(node2.(PostUpdateNode).getPreUpdateNode(),
629-
node1.(PostUpdateNode).getPreUpdateNode(), c)
641+
exists(Node n | implicitBorrow(n, node1.(PostUpdateNode).getPreUpdateNode(), c) |
642+
node2.(PostUpdateNode).getPreUpdateNode() = n
643+
or
644+
// For compound assignments into variables like `x += y`, we do not want flow into
645+
// `[post] x`, as that would create spurious flow when `x` is a parameter. Instead,
646+
// we add the step directly into the SSA definition for `x` after the update.
647+
exists(CompoundAssignmentExpr cae, Expr lhs |
648+
lhs = cae.getLhs() and
649+
lhs = node2.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
650+
n = TExprNode(lhs)
651+
)
652+
)
630653
or
631654
VariableCapture::readStep(node1, c, node2)
632655
}

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,6 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
2020
Stages::DataFlowStage::ref() and
2121
model = "" and
2222
(
23-
exists(BinaryExpr binary |
24-
binary.getOperatorName() = ["+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>"] and
25-
pred.asExpr() = [binary.getLhs(), binary.getRhs()] and
26-
succ.asExpr() = binary
27-
)
28-
or
29-
exists(PrefixExpr prefix |
30-
prefix.getOperatorName() = ["-", "!"] and
31-
pred.asExpr() = prefix.getExpr() and
32-
succ.asExpr() = prefix
33-
)
34-
or
3523
pred.asExpr() = succ.asExpr().(CastExpr).getExpr()
3624
or
3725
exists(IndexExpr index |

rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ module Impl {
131131
* Holds if this operation is overloaded to the method `methodName` of the
132132
* trait `trait`.
133133
*/
134+
pragma[nomagic]
134135
predicate isOverloaded(Trait trait, string methodName, int borrows) {
135136
isOverloaded(this.getOperatorName(), this.getNumberOfOperands(), trait.getCanonicalPath(),
136137
methodName, borrows)

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

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,70 @@ extensions:
99
# Index
1010
- ["<_ as core::ops::index::Index>::index", "Argument[self].Reference.Element", "ReturnValue.Reference", "value", "manual"]
1111
- ["<_ as core::ops::index::IndexMut>::index_mut", "Argument[self].Reference.Element", "ReturnValue.Reference", "value", "manual"]
12-
# Arithmetic
12+
# Unary operators
13+
- ["<_ as core::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "manual"]
14+
- ["<_ as core::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "manual"]
15+
# Arithmetic operators
1316
- ["<_ as core::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "manual"]
1417
- ["<_ as core::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "manual"]
1518
- ["<_ as core::ops::arith::Add>::add", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
19+
- ["<_ as core::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "manual"]
20+
- ["<_ as core::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "manual"]
21+
- ["<_ as core::ops::arith::Sub>::sub", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
22+
- ["<_ as core::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "manual"]
23+
- ["<_ as core::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "manual"]
24+
- ["<_ as core::ops::arith::Mul>::mul", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
25+
- ["<_ as core::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "manual"]
26+
- ["<_ as core::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "manual"]
27+
- ["<_ as core::ops::arith::Div>::div", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
28+
- ["<_ as core::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "manual"]
29+
- ["<_ as core::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "manual"]
30+
- ["<_ as core::ops::arith::Rem>::rem", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
31+
# Arithmetic assignment expressions
32+
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
33+
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
34+
- ["<_ as core::ops::arith::AddAssign>::add_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
35+
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
36+
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
37+
- ["<_ as core::ops::arith::SubAssign>::sub_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
38+
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
39+
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
40+
- ["<_ as core::ops::arith::MulAssign>::mul_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
41+
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
42+
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
43+
- ["<_ as core::ops::arith::DivAssign>::div_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
44+
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[self].Reference", "Argument[self].Reference", "taint", "manual"]
45+
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
46+
- ["<_ as core::ops::arith::RemAssign>::rem_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
47+
# Bitwise operators
48+
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "manual"]
49+
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "manual"]
50+
- ["<_ as core::ops::bit::BitAnd>::bitand", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
51+
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "manual"]
52+
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "manual"]
53+
- ["<_ as core::ops::bit::BitOr>::bitor", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
54+
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "manual"]
55+
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "manual"]
56+
- ["<_ as core::ops::bit::BitXor>::bitxor", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
57+
# Bitwise assignment operators
58+
- ["<_ as core::ops::bit::BitAndAssign>::bitand_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
59+
- ["<_ as core::ops::bit::BitAndAssign>::bitand_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
60+
- ["<_ as core::ops::bit::BitOrAssign>::bitor_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
61+
- ["<_ as core::ops::bit::BitOrAssign>::bitor_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
62+
- ["<_ as core::ops::bit::BitXorAssign>::bitxor_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
63+
- ["<_ as core::ops::bit::BitXorAssign>::bitxor_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
64+
# Shift operators
65+
- ["<_ as core::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "manual"]
66+
- ["<_ as core::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "manual"]
67+
- ["<_ as core::ops::bit::Shl>::shl", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
68+
- ["<_ as core::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "manual"]
69+
- ["<_ as core::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "manual"]
70+
- ["<_ as core::ops::bit::Shr>::shr", "Argument[0].Reference", "ReturnValue", "taint", "manual"]
71+
# Shift assignment operators
72+
- ["<_ as core::ops::bit::ShlAssign>::shl_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
73+
- ["<_ as core::ops::bit::ShlAssign>::shl_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
74+
- ["<_ as core::ops::bit::ShrAssign>::shr_assign", "Argument[0]", "Argument[self].Reference", "taint", "manual"]
75+
- ["<_ as core::ops::bit::ShrAssign>::shr_assign", "Argument[0].Reference", "Argument[self].Reference", "taint", "manual"]
1676
# Clone
1777
- ["<_ as core::clone::Clone>::clone", "Argument[self].Reference", "ReturnValue", "value", "manual"]
1878
# Conversions

0 commit comments

Comments
 (0)