Skip to content

Commit 4825480

Browse files
aschackmullMathiasVP
authored andcommitted
WIP
C++: Add support for MaD barriers and barrier guards.
1 parent 07ac8a5 commit 4825480

2 files changed

Lines changed: 69 additions & 4 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595

9696
import cpp
9797
private import new.DataFlow
98+
private import semmle.code.cpp.controlflow.IRGuards
9899
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
99100
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
100101
private import internal.FlowSummaryImpl
@@ -367,6 +368,8 @@ private predicate elementSpec(
367368
) {
368369
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
369370
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
371+
barrierModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
372+
barrierGuardModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _) or
370373
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
371374
}
372375

@@ -1028,6 +1031,52 @@ private module Cached {
10281031
isSinkNode(n, kind, model) and n.asNode() = node
10291032
)
10301033
}
1034+
1035+
private newtype TKindModelPair =
1036+
TMkPair(string kind, string model) { isBarrierGuardNode(_, _, kind, model) }
1037+
1038+
private GuardValue convertAcceptingValue(Public::AcceptingValue av) {
1039+
av.isTrue() and result.asBooleanValue() = true
1040+
or
1041+
av.isFalse() and result.asBooleanValue() = false
1042+
or
1043+
av.isNoException() and result.getDualValue().isThrowsException()
1044+
or
1045+
av.isZero() and result.asIntValue() = 0
1046+
or
1047+
av.isNotZero() and result.getDualValue().asIntValue() = 0
1048+
or
1049+
av.isNull() and result.isNullValue()
1050+
or
1051+
av.isNotNull() and result.isNonNullValue()
1052+
}
1053+
1054+
private predicate barrierGuardChecks(IRGuardCondition g, Expr e, GuardValue gv, TKindModelPair kmp) {
1055+
exists(
1056+
SourceSinkInterpretationInput::InterpretNode n, Public::AcceptingValue acceptingvalue,
1057+
string kind, string model
1058+
|
1059+
isBarrierGuardNode(n, acceptingvalue, kind, model) and
1060+
n.asNode().asExpr() = e and
1061+
kmp = TMkPair(kind, model) and
1062+
gv = convertAcceptingValue(acceptingvalue) and
1063+
n.asNode().(ArgumentNode).getCallInstruction() = g
1064+
)
1065+
}
1066+
1067+
/**
1068+
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
1069+
* model.
1070+
*/
1071+
cached
1072+
predicate barrierNode(DataFlow::Node node, string kind, string model) {
1073+
exists(SourceSinkInterpretationInput::InterpretNode n |
1074+
isBarrierNode(n, kind, model) and n.asNode() = node
1075+
)
1076+
or
1077+
DataFlow::ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
1078+
model)) = node
1079+
}
10311080
}
10321081

10331082
import Cached
@@ -1044,6 +1093,12 @@ predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind,
10441093
*/
10451094
predicate sinkNode(DataFlow::Node node, string kind) { sinkNode(node, kind, _) }
10461095

1096+
/**
1097+
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
1098+
* model.
1099+
*/
1100+
predicate barrierNode(DataFlow::Node node, string kind) { barrierNode(node, kind, _) }
1101+
10471102
private predicate interpretSummary(
10481103
Function f, string input, string output, string kind, string provenance, string model
10491104
) {

cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,26 @@ module SourceSinkInterpretationInput implements
149149
}
150150

151151
predicate barrierElement(
152-
Element n, string output, string kind, Public::Provenance provenance, string model
152+
Element e, string output, string kind, Public::Provenance provenance, string model
153153
) {
154-
none()
154+
exists(
155+
string namespace, string type, boolean subtypes, string name, string signature, string ext
156+
|
157+
barrierModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
158+
e = interpretElement(namespace, type, subtypes, name, signature, ext)
159+
)
155160
}
156161

157162
predicate barrierGuardElement(
158-
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
163+
Element e, string input, Public::AcceptingValue acceptingvalue, string kind,
159164
Public::Provenance provenance, string model
160165
) {
161-
none()
166+
exists(
167+
string package, string type, boolean subtypes, string name, string signature, string ext
168+
|
169+
barrierGuardModel(package, type, subtypes, name, signature, ext, input, acceptingvalue, kind, provenance, model) and
170+
e = interpretElement(package, type, subtypes, name, signature, ext)
171+
)
162172
}
163173

164174
private newtype TInterpretNode =

0 commit comments

Comments
 (0)