Skip to content

Commit 0ff37f1

Browse files
authored
Merge pull request #18486 from MathiasVP/indirect-instruction-barriers
C++: Add a `BarrierGuard` module for indirect instruction/operand nodes.
2 parents 7196892 + d9d0d93 commit 0ff37f1

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* Add a new predicate `getAnIndirectBarrier` to the parameterized module `InstructionBarrierGuard` in `semmle.code.cpp.dataflow.new.DataFlow` for computing indirect dataflow nodes that are guarded by a given instruction. This predicate is similar to the `getAnIndirectBarrier` predicate on the parameterized module `BarrierGuard`.

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,6 +2494,36 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
24942494
result = TSsaPhiInputNode(phi, input)
24952495
)
24962496
}
2497+
2498+
bindingset[value, n]
2499+
pragma[inline_late]
2500+
private predicate indirectOperandHasValueNumber(ValueNumber value, int indirectionIndex, Node n) {
2501+
exists(Operand use |
2502+
use = value.getAnInstruction().getAUse() and
2503+
n.asIndirectOperand(indirectionIndex) = use
2504+
)
2505+
}
2506+
2507+
/**
2508+
* Gets an indirect node with indirection index `indirectionIndex` that is
2509+
* safely guarded by the given guard check.
2510+
*/
2511+
Node getAnIndirectBarrierNode(int indirectionIndex) {
2512+
exists(IRGuardCondition g, ValueNumber value, boolean edge |
2513+
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
2514+
indirectOperandHasValueNumber(value, indirectionIndex, result) and
2515+
controls(g, result, edge)
2516+
)
2517+
or
2518+
exists(
2519+
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
2520+
|
2521+
instructionGuardChecks(g, def.getARead().asIndirectOperand(indirectionIndex).getDef(), branch) and
2522+
guardControlsPhiInput(g, branch, def, pragma[only_bind_into](input),
2523+
pragma[only_bind_into](phi)) and
2524+
result = TSsaPhiInputNode(phi, input)
2525+
)
2526+
}
24972527
}
24982528

24992529
/**
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
bool checkArgument(int* x);
2+
3+
void sink(int);
4+
5+
void testCheckArgument(int* p) {
6+
if (checkArgument(p)) {
7+
sink(*p); // $ barrier barrier=1
8+
}
9+
}

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

Whitespace-only changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import cpp
2+
import semmle.code.cpp.dataflow.new.DataFlow
3+
import semmle.code.cpp.controlflow.IRGuards
4+
import utils.test.InlineExpectationsTest
5+
6+
predicate instructionGuardChecks(IRGuardCondition gc, Instruction checked, boolean branch) {
7+
exists(CallInstruction call |
8+
call.getStaticCallTarget().hasName("checkArgument") and
9+
checked = call.getAnArgument() and
10+
gc.comparesEq(call.getAUse(), 0, false, any(BooleanValue bv | bv.getValue() = branch))
11+
)
12+
}
13+
14+
module BarrierGuard = DataFlow::InstructionBarrierGuard<instructionGuardChecks/3>;
15+
16+
predicate indirectBarrierGuard(DataFlow::Node node, int indirectionIndex) {
17+
node = BarrierGuard::getAnIndirectBarrierNode(indirectionIndex)
18+
}
19+
20+
predicate barrierGuard(DataFlow::Node node) { node = BarrierGuard::getABarrierNode() }
21+
22+
module Test implements TestSig {
23+
string getARelevantTag() { result = "barrier" }
24+
25+
predicate hasActualResult(Location location, string element, string tag, string value) {
26+
exists(DataFlow::Node node |
27+
barrierGuard(node) and
28+
value = ""
29+
or
30+
exists(int indirectionIndex |
31+
indirectBarrierGuard(node, indirectionIndex) and
32+
value = indirectionIndex.toString()
33+
)
34+
|
35+
tag = "barrier" and
36+
element = node.toString() and
37+
location = node.getLocation()
38+
)
39+
}
40+
}
41+
42+
import MakeTest<Test>

0 commit comments

Comments
 (0)