Skip to content

Commit 44cc19c

Browse files
committed
C++: Handle phi inputs in barrier guards logic.
1 parent 05d46a6 commit 44cc19c

File tree

1 file changed

+66
-7
lines changed

1 file changed

+66
-7
lines changed

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

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ class Node extends TIRDataFlowNode {
159159
/** Gets the operands corresponding to this node, if any. */
160160
Operand asOperand() { result = this.(OperandNode).getOperand() }
161161

162+
/**
163+
* Gets the operand that is indirectly tracked by this node behind `index`
164+
* number of indirections.
165+
*/
166+
Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) }
167+
162168
/**
163169
* Holds if this node is at index `i` in basic block `block`.
164170
*
@@ -2673,6 +2679,22 @@ class ContentSet instanceof Content {
26732679
}
26742680
}
26752681

2682+
pragma[nomagic]
2683+
private predicate guardControlsPhiInput(
2684+
IRGuardCondition g, boolean branch, Ssa::Definition def, IRBlock input, Ssa::PhiInputNodeExt phi
2685+
) {
2686+
phi.hasInputFromBlock(def, input) and
2687+
(
2688+
g.controls(input, branch)
2689+
or
2690+
exists(EdgeKind kind |
2691+
g.getBlock() = input and
2692+
kind = getConditionalEdge(branch) and
2693+
input.getSuccessor(kind) = phi.getBasicBlock()
2694+
)
2695+
)
2696+
}
2697+
26762698
/**
26772699
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
26782700
*
@@ -2721,13 +2743,22 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27212743
*
27222744
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
27232745
*/
2724-
ExprNode getABarrierNode() {
2746+
Node getABarrierNode() {
27252747
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
27262748
e = value.getAnInstruction().getConvertedResultExpression() and
2727-
result.getConvertedExpr() = e and
2749+
result.asConvertedExpr() = e and
27282750
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
27292751
g.controls(result.getBasicBlock(), edge)
27302752
)
2753+
or
2754+
exists(
2755+
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
2756+
Ssa::PhiInputNodeExt phi
2757+
|
2758+
guardChecks(g, def.getARead().asOperand().getDef().getConvertedResultExpression(), branch) and
2759+
guardControlsPhiInput(g, branch, def, input, phi) and
2760+
result = TSsaPhiInputNode(phi.getPhi(), input)
2761+
)
27312762
}
27322763

27332764
/**
@@ -2763,7 +2794,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27632794
*
27642795
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
27652796
*/
2766-
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
2797+
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
27672798

27682799
/**
27692800
* Gets an indirect expression node with indirection index `indirectionIndex` that is
@@ -2799,13 +2830,24 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
27992830
*
28002831
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
28012832
*/
2802-
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
2833+
Node getAnIndirectBarrierNode(int indirectionIndex) {
28032834
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
28042835
e = value.getAnInstruction().getConvertedResultExpression() and
2805-
result.getConvertedExpr(indirectionIndex) = e and
2836+
result.asIndirectConvertedExpr(indirectionIndex) = e and
28062837
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
28072838
g.controls(result.getBasicBlock(), edge)
28082839
)
2840+
or
2841+
exists(
2842+
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
2843+
Ssa::PhiInputNodeExt phi
2844+
|
2845+
guardChecks(g,
2846+
def.getARead().asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
2847+
branch) and
2848+
guardControlsPhiInput(g, branch, def, input, phi) and
2849+
result = TSsaPhiInputNode(phi.getPhi(), input)
2850+
)
28092851
}
28102852
}
28112853

@@ -2814,6 +2856,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
28142856
*/
28152857
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
28162858

2859+
private EdgeKind getConditionalEdge(boolean branch) {
2860+
branch = true and
2861+
result instanceof TrueEdge
2862+
or
2863+
branch = false and
2864+
result instanceof FalseEdge
2865+
}
2866+
28172867
/**
28182868
* Provides a set of barrier nodes for a guard that validates an instruction.
28192869
*
@@ -2822,12 +2872,21 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
28222872
*/
28232873
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
28242874
/** Gets a node that is safely guarded by the given guard check. */
2825-
ExprNode getABarrierNode() {
2875+
Node getABarrierNode() {
28262876
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
28272877
instructionGuardChecks(g, value.getAnInstruction(), edge) and
28282878
use = value.getAnInstruction().getAUse() and
28292879
result.asOperand() = use and
2830-
g.controls(use.getDef().getBlock(), edge)
2880+
g.controls(result.getBasicBlock(), edge)
2881+
)
2882+
or
2883+
exists(
2884+
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
2885+
Ssa::PhiInputNodeExt phi
2886+
|
2887+
instructionGuardChecks(g, def.getARead().asOperand().getDef(), branch) and
2888+
guardControlsPhiInput(g, branch, def, input, phi) and
2889+
result = TSsaPhiInputNode(phi.getPhi(), input)
28312890
)
28322891
}
28332892
}

0 commit comments

Comments
 (0)