Skip to content

Commit 56d459a

Browse files
committed
WIP barrier guards 2
1 parent 2efe759 commit 56d459a

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

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

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,14 +1157,48 @@ private module Cached {
11571157
cached
11581158
predicate sinkNode(Node n, string kind) { n.(FlowSummaryNode).isSink(kind, _) }
11591159

1160-
/** Holds if `n` is a flow barrier of kind `kind`. */
1160+
private newtype TKindModelPair =
1161+
TMkPair(string kind, string model) { FlowSummaryImpl::Private::barrierSpec(_, _, kind, model) }
1162+
1163+
private boolean convertAcceptingValue(FlowSummaryImpl::Public::AcceptingValue av) {
1164+
av.isTrue() and result = true
1165+
or
1166+
av.isFalse() and result = false
1167+
// Remaining cases are not supported yet, they depend on the shared Guards library.
1168+
// or
1169+
// av.isNoException() and result.getDualValue().isThrowsException()
1170+
// or
1171+
// av.isZero() and result.asIntValue() = 0
1172+
// or
1173+
// av.isNotZero() and result.getDualValue().asIntValue() = 0
1174+
// or
1175+
// av.isNull() and result.isNullValue()
1176+
// or
1177+
// av.isNotNull() and result.isNonNullValue()
1178+
}
1179+
1180+
private predicate barrierGuardChecks(Node g, Expr e, boolean gv, TKindModelPair kmp) {
1181+
exists(
1182+
FlowSummaryImpl::Public::BarrierElement n,
1183+
FlowSummaryImpl::Public::AcceptingValue acceptingvalue, string kind, string model
1184+
|
1185+
FlowSummaryImpl::Private::barrierSpec(n, acceptingvalue, kind, model) and
1186+
n.asNode().asExpr() = e and
1187+
kmp = TMkPair(kind, model) and
1188+
gv = convertAcceptingValue(acceptingvalue)
1189+
|
1190+
g.asExpr().(CallExpr).getAnArgument() = e // TODO: qualifier?
1191+
)
1192+
}
1193+
1194+
/** Holds if `n` is a flow barrier of kind `kind` and model `model`. */
11611195
cached
1162-
predicate barrierNode(Node n, string kind) {
1196+
predicate barrierNode(Node n, string kind, string model) {
11631197
exists(
11641198
FlowSummaryImpl::Public::BarrierElement b,
11651199
FlowSummaryImpl::Private::SummaryComponentStack stack
11661200
|
1167-
FlowSummaryImpl::Private::barrierSpec(b, stack, kind, _)
1201+
FlowSummaryImpl::Private::barrierSpec(b, stack, kind, model)
11681202
|
11691203
n = FlowSummaryImpl::StepsInput::getSourceNode(b, stack, false)
11701204
or
@@ -1174,6 +1208,9 @@ private module Cached {
11741208
.(PostUpdateNode)
11751209
.getPreUpdateNode()
11761210
)
1211+
or
1212+
ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
1213+
model)) = n
11771214
}
11781215

11791216
/**
@@ -1199,3 +1236,34 @@ private module Cached {
11991236
}
12001237

12011238
import Cached
1239+
1240+
/** Holds if `n` is a flow barrier of kind `kind`. */
1241+
predicate barrierNode(Node n, string kind) { barrierNode(n, kind, _) }
1242+
1243+
bindingset[this]
1244+
private signature class ParamSig;
1245+
1246+
private module WithParam<ParamSig P> {
1247+
/**
1248+
* Holds if the guard `g` validates the expression `e` upon evaluating to `gv`.
1249+
*
1250+
* The expression `e` is expected to be a syntactic part of the guard `g`.
1251+
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
1252+
* the argument `x`.
1253+
*/
1254+
signature predicate guardChecksSig(AstNode g, Expr e, boolean branch, P param);
1255+
}
1256+
1257+
/**
1258+
* Provides a set of barrier nodes for a guard that validates an expression.
1259+
*
1260+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
1261+
* in data flow and taint tracking.
1262+
*/
1263+
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
1264+
/** Gets a node that is safely guarded by the given guard check. */
1265+
Node getABarrierNode(P param) {
1266+
SsaFlow::asNode(result) =
1267+
SsaImpl::DataFlowIntegration::ParameterizedBarrierGuard<P, guardChecks/4>::getABarrierNode(param)
1268+
}
1269+
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,31 @@ private module Cached {
305305

306306
predicate getABarrierNode = getABarrierNodeImpl/0;
307307
}
308+
309+
bindingset[this]
310+
private signature class ParamSig;
311+
312+
private module WithParam<ParamSig P> {
313+
signature predicate guardChecksSig(AstNode g, Expr e, boolean branch, P param);
314+
}
315+
316+
overlay[global]
317+
cached // nothing is actually cached
318+
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
319+
private predicate guardChecksAdjTypes(
320+
DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e,
321+
DataFlowIntegrationInput::GuardValue branch, P param
322+
) {
323+
guardChecks(g, e, branch, param)
324+
}
325+
326+
private Node getABarrierNodeImpl(P param) {
327+
result =
328+
DataFlowIntegrationImpl::BarrierGuardWithState<P, guardChecksAdjTypes/4>::getABarrierNode(param)
329+
}
330+
331+
predicate getABarrierNode = getABarrierNodeImpl/1;
332+
}
308333
}
309334
}
310335

0 commit comments

Comments
 (0)