Skip to content

Commit bbb8d29

Browse files
committed
C/C++: Deprecate BarrierGuard class.
1 parent 1b374e2 commit bbb8d29

File tree

6 files changed

+94
-40
lines changed

6 files changed

+94
-40
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,34 @@ class ContentSet instanceof Content {
850850
}
851851

852852
/**
853+
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
854+
*
855+
* The expression `e` is expected to be a syntactic part of the guard `g`.
856+
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
857+
* the argument `x`.
858+
*/
859+
signature predicate guardChecksSig(GuardCondition g, Expr e, boolean branch);
860+
861+
/**
862+
* Provides a set of barrier nodes for a guard that validates an expression.
863+
*
864+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
865+
* in data flow and taint tracking.
866+
*/
867+
module BarrierGuard<guardChecksSig/3 guardChecks> {
868+
/** Gets a node that is safely guarded by the given guard check. */
869+
ExprNode getABarrierNode() {
870+
exists(GuardCondition g, SsaDefinition def, Variable v, boolean branch |
871+
result.getExpr() = def.getAUse(v) and
872+
guardChecks(g, def.getAUse(v), branch) and
873+
g.controls(result.getExpr().getBasicBlock(), branch)
874+
)
875+
}
876+
}
877+
878+
/**
879+
* DEPRECATED: Use `BarrierGuard` module instead.
880+
*
853881
* A guard that validates some expression.
854882
*
855883
* To use this in a configuration, extend the class and provide a
@@ -858,7 +886,7 @@ class ContentSet instanceof Content {
858886
*
859887
* It is important that all extending classes in scope are disjoint.
860888
*/
861-
class BarrierGuard extends GuardCondition {
889+
deprecated class BarrierGuard extends GuardCondition {
862890
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
863891
abstract predicate checks(Expr e, boolean b);
864892

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
4747
*/
4848
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
4949

50-
/**
51-
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
52-
* but not in local taint.
53-
*/
54-
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
55-
5650
/**
5751
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
5852
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,56 @@ class ContentSet instanceof Content {
10921092
}
10931093

10941094
/**
1095+
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
1096+
*
1097+
* The expression `e` is expected to be a syntactic part of the guard `g`.
1098+
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
1099+
* the argument `x`.
1100+
*/
1101+
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
1102+
1103+
/**
1104+
* Provides a set of barrier nodes for a guard that validates an expression.
1105+
*
1106+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
1107+
* in data flow and taint tracking.
1108+
*/
1109+
module BarrierGuard<guardChecksSig/3 guardChecks> {
1110+
/** Gets a node that is safely guarded by the given guard check. */
1111+
ExprNode getABarrierNode() {
1112+
exists(IRGuardCondition g, ValueNumber value, boolean edge |
1113+
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
1114+
result.asInstruction() = value.getAnInstruction() and
1115+
g.controls(result.asInstruction().getBlock(), edge)
1116+
)
1117+
}
1118+
}
1119+
1120+
/**
1121+
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
1122+
*/
1123+
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
1124+
1125+
/**
1126+
* Provides a set of barrier nodes for a guard that validates an instruction.
1127+
*
1128+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
1129+
* in data flow and taint tracking.
1130+
*/
1131+
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
1132+
/** Gets a node that is safely guarded by the given guard check. */
1133+
ExprNode getABarrierNode() {
1134+
exists(IRGuardCondition g, ValueNumber value, boolean edge |
1135+
instructionGuardChecks(g, value.getAnInstruction(), edge) and
1136+
result.asInstruction() = value.getAnInstruction() and
1137+
g.controls(result.asInstruction().getBlock(), edge)
1138+
)
1139+
}
1140+
}
1141+
1142+
/**
1143+
* DEPRECATED: Use `BarrierGuard` module instead.
1144+
*
10951145
* A guard that validates some instruction.
10961146
*
10971147
* To use this in a configuration, extend the class and provide a
@@ -1100,7 +1150,7 @@ class ContentSet instanceof Content {
11001150
*
11011151
* It is important that all extending classes in scope are disjoint.
11021152
*/
1103-
class BarrierGuard extends IRGuardCondition {
1153+
deprecated class BarrierGuard extends IRGuardCondition {
11041154
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
11051155
predicate checksInstr(Instruction instr, boolean b) { none() }
11061156

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,6 @@ private string getNodeProperty(DataFlow::Node node, string key) {
9494
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
9595
or
9696
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
97-
or
98-
exists(DataFlow::BarrierGuard guard |
99-
any(DataFlow::Configuration cfg).isBarrierGuard(guard) and
100-
node = guard.getAGuardedNode() and
101-
kind = "guard(" + guard.getResultId() + ")"
102-
)
10397
|
10498
kind, ", "
10599
)

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
163163
*/
164164
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
165165

166-
/**
167-
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
168-
* but not in local taint.
169-
*/
170-
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
171-
172166
/**
173167
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
174168
* modeled function.

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@ import TestUtilities.dataflow.FlowTestCommon
22

33
module AstTest {
44
private import semmle.code.cpp.dataflow.DataFlow
5+
private import semmle.code.cpp.controlflow.Guards
56

67
/**
78
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
89
* S in `if (guarded(x)) S`.
910
*/
1011
// This is tested in `BarrierGuard.cpp`.
11-
class TestBarrierGuard extends DataFlow::BarrierGuard {
12-
TestBarrierGuard() { this.(FunctionCall).getTarget().getName() = "guarded" }
13-
14-
override predicate checks(Expr checked, boolean isTrue) {
15-
checked = this.(FunctionCall).getArgument(0) and
16-
isTrue = true
17-
}
12+
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
13+
g.(FunctionCall).getTarget().getName() = "guarded" and
14+
checked = g.(FunctionCall).getArgument(0) and
15+
isTrue = true
1816
}
1917

2018
/** Common data flow configuration to be used by tests. */
@@ -40,29 +38,26 @@ module AstTest {
4038
}
4139

4240
override predicate isBarrier(DataFlow::Node barrier) {
43-
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier")
41+
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
42+
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
4443
}
45-
46-
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
4744
}
4845
}
4946

5047
module IRTest {
5148
private import semmle.code.cpp.ir.dataflow.DataFlow
5249
private import semmle.code.cpp.ir.IR
50+
private import semmle.code.cpp.controlflow.IRGuards
5351

5452
/**
5553
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
5654
* S in `if (guarded(x)) S`.
5755
*/
5856
// This is tested in `BarrierGuard.cpp`.
59-
class TestBarrierGuard extends DataFlow::BarrierGuard {
60-
TestBarrierGuard() { this.(CallInstruction).getStaticCallTarget().getName() = "guarded" }
61-
62-
override predicate checksInstr(Instruction checked, boolean isTrue) {
63-
checked = this.(CallInstruction).getPositionalArgument(0) and
64-
isTrue = true
65-
}
57+
predicate testBarrierGuard(IRGuardCondition g, Instruction checked, boolean isTrue) {
58+
g.(CallInstruction).getStaticCallTarget().getName() = "guarded" and
59+
checked = g.(CallInstruction).getPositionalArgument(0) and
60+
isTrue = true
6661
}
6762

6863
/** Common data flow configuration to be used by tests. */
@@ -93,10 +88,9 @@ module IRTest {
9388
}
9489

9590
override predicate isBarrier(DataFlow::Node barrier) {
96-
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier")
91+
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
92+
barrier = DataFlow::InstructionBarrierGuard<testBarrierGuard/3>::getABarrierNode()
9793
}
98-
99-
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
10094
}
10195

10296
private predicate readsVariable(LoadInstruction load, Variable var) {

0 commit comments

Comments
 (0)