Skip to content

Commit a11b271

Browse files
committed
C++: Finish up implementation of MaD barriers.
1 parent 4825480 commit a11b271

3 files changed

Lines changed: 52 additions & 8 deletions

File tree

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

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,11 @@ private module Cached {
10401040
or
10411041
av.isFalse() and result.asBooleanValue() = false
10421042
or
1043+
// NOTE: The below cases don't contribute anything currently since the
1044+
// callers immediate uses `.asBooleanValue()` to convert the `GuardValue`
1045+
// to a boolean. Once we're willing to accept the breaking change of
1046+
// converting the barrier guard API to use `GuardValue`s instead `Boolean`s
1047+
// we can remove this restriction.
10431048
av.isNoException() and result.getDualValue().isThrowsException()
10441049
or
10451050
av.isZero() and result.asIntValue() = 0
@@ -1051,16 +1056,42 @@ private module Cached {
10511056
av.isNotNull() and result.isNonNullValue()
10521057
}
10531058

1054-
private predicate barrierGuardChecks(IRGuardCondition g, Expr e, GuardValue gv, TKindModelPair kmp) {
1059+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
1060+
1061+
private predicate barrierGuardChecks(IRGuardCondition g, Expr e, boolean gv, TKindModelPair kmp) {
10551062
exists(
10561063
SourceSinkInterpretationInput::InterpretNode n, Public::AcceptingValue acceptingvalue,
10571064
string kind, string model
10581065
|
10591066
isBarrierGuardNode(n, acceptingvalue, kind, model) and
10601067
n.asNode().asExpr() = e and
10611068
kmp = TMkPair(kind, model) and
1062-
gv = convertAcceptingValue(acceptingvalue) and
1063-
n.asNode().(ArgumentNode).getCallInstruction() = g
1069+
gv = convertAcceptingValue(acceptingvalue).asBooleanValue() and
1070+
n.asNode().(Private::ArgumentNode).getCall().asCallInstruction() = g
1071+
)
1072+
}
1073+
1074+
private newtype TKindModelPairIntPair =
1075+
MkKindModelPairIntPair(TKindModelPair pair, int indirectionIndex) {
1076+
indirectionIndex > 0 and
1077+
Private::nodeHasInstruction(_, _, indirectionIndex) and
1078+
exists(pair)
1079+
}
1080+
1081+
private predicate indirectBarrierGuardChecks(
1082+
IRGuardCondition g, Expr e, boolean gv, TKindModelPairIntPair kmp
1083+
) {
1084+
exists(
1085+
SourceSinkInterpretationInput::InterpretNode interpretNode,
1086+
Public::AcceptingValue acceptingvalue, string kind, string model, int indirectionIndex,
1087+
Private::ArgumentNode arg
1088+
|
1089+
isBarrierGuardNode(interpretNode, acceptingvalue, kind, model) and
1090+
arg = interpretNode.asNode() and
1091+
arg.asIndirectExpr(indirectionIndex) = e and
1092+
kmp = MkKindModelPairIntPair(TMkPair(kind, model), indirectionIndex) and
1093+
gv = convertAcceptingValue(acceptingvalue).asBooleanValue() and
1094+
arg.getCall().asCallInstruction() = g
10641095
)
10651096
}
10661097

@@ -1076,6 +1107,9 @@ private module Cached {
10761107
or
10771108
DataFlow::ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
10781109
model)) = node
1110+
or
1111+
DataFlow::ParameterizedBarrierGuard<TKindModelPairIntPair, indirectBarrierGuardChecks/4>::getAnIndirectBarrierNode(MkKindModelPairIntPair(TMkPair(kind,
1112+
model), _)) = node
10791113
}
10801114
}
10811115

cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,25 @@ void sink(int*);
2626
void test_mad(int x, int* p) {
2727
{
2828
if(is_clean_value(&x)) {
29-
sink(x); // $ MISSING: external=int
29+
sink(x); // $ external=int
3030
}
3131
}
3232

3333
{
3434
if(is_clean_value(p)) {
35-
sink(*p); // $ MISSING: external=int
35+
sink(*p); // $ external=int
3636
}
3737
}
3838

3939
{
4040
if(is_clean_pointer(p)) {
41-
sink(p); // $ MISSING: external=int*
41+
sink(p); // $ external=int*
4242
}
4343
}
4444

4545
{
4646
if(is_clean_pointer(&x)) {
47-
sink(x); // $ MISSING: external=glval<int>
47+
sink(x); // $ external=glval<int>
4848
}
4949
}
5050
}

cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.ql

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ predicate barrierGuard(DataFlow::Node node, string s) {
2828
else s = node.getType().toString().replaceAll(" ", "")
2929
}
3030

31+
predicate externalBarrierGuard(DataFlow::Node node, string s) {
32+
barrierNode(node, "test-barrier") and
33+
if node.isGLValue()
34+
then s = "glval<" + node.getType().toString().replaceAll(" ", "") + ">"
35+
else s = node.getType().toString().replaceAll(" ", "")
36+
}
37+
3138
module Test implements TestSig {
32-
string getARelevantTag() { result = ["barrier", "indirect_barrier"] }
39+
string getARelevantTag() { result = ["barrier", "indirect_barrier", "external"] }
3340

3441
predicate hasActualResult(Location location, string element, string tag, string value) {
3542
exists(DataFlow::Node node |
@@ -38,6 +45,9 @@ module Test implements TestSig {
3845
or
3946
barrierGuard(node, value) and
4047
tag = "barrier"
48+
or
49+
externalBarrierGuard(node, value) and
50+
tag = "external"
4151
|
4252
element = node.toString() and
4353
location = node.getLocation()

0 commit comments

Comments
 (0)