Skip to content

Commit 6f6ef8a

Browse files
committed
Rust: Taint flow through operations using MaD
1 parent 7958822 commit 6f6ef8a

File tree

20 files changed

+408
-191
lines changed

20 files changed

+408
-191
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
@@ -255,8 +255,11 @@ module LocalFlow {
255255
)
256256
or
257257
// An edge from a pattern/expression to its corresponding SSA definition.
258-
nodeFrom.(AstNodeNode).getAstNode() =
259-
nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess()
258+
exists(AstNode n |
259+
n = nodeTo.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
260+
n = nodeFrom.(AstNodeNode).getAstNode() and
261+
not n = any(CompoundAssignmentExpr cae).getLhs()
262+
)
260263
or
261264
nodeFrom.(SourceParameterNode).getParameter().(Param).getPat() = nodeTo.asPat()
262265
or
@@ -425,13 +428,23 @@ module RustDataFlow implements InputSig<Location> {
425428

426429
final class ReturnKind = ReturnKindAlias;
427430

431+
private Function getStaticTargetExt(Call c) {
432+
result = c.getStaticTarget()
433+
or
434+
not exists(c.getStaticTarget()) and
435+
exists(TraitItemNode t, string methodName |
436+
c.(Operation).isOverloaded(t, methodName, _) and
437+
result = t.getAssocItem(methodName)
438+
)
439+
}
440+
428441
/** Gets a viable implementation of the target of the given `Call`. */
429442
DataFlowCallable viableCallable(DataFlowCall call) {
430443
exists(Call c | c = call.asCall() |
431444
result.asCfgScope() = c.getARuntimeTarget()
432445
or
433446
exists(SummarizedCallable sc, Function staticTarget |
434-
staticTarget = c.getStaticTarget() and
447+
staticTarget = getStaticTargetExt(c) and
435448
sc = result.asSummarizedCallable()
436449
|
437450
sc = staticTarget
@@ -632,8 +645,18 @@ module RustDataFlow implements InputSig<Location> {
632645
implicitDeref(node1, node2, c)
633646
or
634647
// A read step dual to the store step for implicit borrows.
635-
implicitBorrow(node2.(PostUpdateNode).getPreUpdateNode(),
636-
node1.(PostUpdateNode).getPreUpdateNode(), c)
648+
exists(Node n | implicitBorrow(n, node1.(PostUpdateNode).getPreUpdateNode(), c) |
649+
node2.(PostUpdateNode).getPreUpdateNode() = n
650+
or
651+
// For compound assignments into variables like `x += y`, we do not want flow into
652+
// `[post] x`, as that would create spurious flow when `x` is a parameter. Instead,
653+
// we add the step directly into the SSA definition for `x` after the update.
654+
exists(CompoundAssignmentExpr cae, Expr lhs |
655+
lhs = cae.getLhs() and
656+
lhs = node2.(SsaNode).asDefinition().(Ssa::WriteDefinition).getWriteAccess() and
657+
n = TExprNode(lhs)
658+
)
659+
)
637660
or
638661
VariableCapture::readStep(node1, c, node2)
639662
}

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)