mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #18486 from MathiasVP/indirect-instruction-barriers
C++: Add a `BarrierGuard` module for indirect instruction/operand nodes.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* 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`.
|
||||
@@ -2494,6 +2494,36 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[value, n]
|
||||
pragma[inline_late]
|
||||
private predicate indirectOperandHasValueNumber(ValueNumber value, int indirectionIndex, Node n) {
|
||||
exists(Operand use |
|
||||
use = value.getAnInstruction().getAUse() and
|
||||
n.asIndirectOperand(indirectionIndex) = use
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an indirect node with indirection index `indirectionIndex` that is
|
||||
* safely guarded by the given guard check.
|
||||
*/
|
||||
Node getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
|
||||
indirectOperandHasValueNumber(value, indirectionIndex, result) and
|
||||
controls(g, result, edge)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||
|
|
||||
instructionGuardChecks(g, def.getARead().asIndirectOperand(indirectionIndex).getDef(), branch) and
|
||||
guardControlsPhiInput(g, branch, def, pragma[only_bind_into](input),
|
||||
pragma[only_bind_into](phi)) and
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
bool checkArgument(int* x);
|
||||
|
||||
void sink(int);
|
||||
|
||||
void testCheckArgument(int* p) {
|
||||
if (checkArgument(p)) {
|
||||
sink(*p); // $ barrier barrier=1
|
||||
}
|
||||
}
|
||||
42
cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.ql
Normal file
42
cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.ql
Normal file
@@ -0,0 +1,42 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
import utils.test.InlineExpectationsTest
|
||||
|
||||
predicate instructionGuardChecks(IRGuardCondition gc, Instruction checked, boolean branch) {
|
||||
exists(CallInstruction call |
|
||||
call.getStaticCallTarget().hasName("checkArgument") and
|
||||
checked = call.getAnArgument() and
|
||||
gc.comparesEq(call.getAUse(), 0, false, any(BooleanValue bv | bv.getValue() = branch))
|
||||
)
|
||||
}
|
||||
|
||||
module BarrierGuard = DataFlow::InstructionBarrierGuard<instructionGuardChecks/3>;
|
||||
|
||||
predicate indirectBarrierGuard(DataFlow::Node node, int indirectionIndex) {
|
||||
node = BarrierGuard::getAnIndirectBarrierNode(indirectionIndex)
|
||||
}
|
||||
|
||||
predicate barrierGuard(DataFlow::Node node) { node = BarrierGuard::getABarrierNode() }
|
||||
|
||||
module Test implements TestSig {
|
||||
string getARelevantTag() { result = "barrier" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(DataFlow::Node node |
|
||||
barrierGuard(node) and
|
||||
value = ""
|
||||
or
|
||||
exists(int indirectionIndex |
|
||||
indirectBarrierGuard(node, indirectionIndex) and
|
||||
value = indirectionIndex.toString()
|
||||
)
|
||||
|
|
||||
tag = "barrier" and
|
||||
element = node.toString() and
|
||||
location = node.getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<Test>
|
||||
Reference in New Issue
Block a user