mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
C++: Handle phi inputs in barrier guards logic.
This commit is contained in:
@@ -159,6 +159,12 @@ class Node extends TIRDataFlowNode {
|
|||||||
/** Gets the operands corresponding to this node, if any. */
|
/** Gets the operands corresponding to this node, if any. */
|
||||||
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operand that is indirectly tracked by this node behind `index`
|
||||||
|
* number of indirections.
|
||||||
|
*/
|
||||||
|
Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this node is at index `i` in basic block `block`.
|
* Holds if this node is at index `i` in basic block `block`.
|
||||||
*
|
*
|
||||||
@@ -2673,6 +2679,22 @@ class ContentSet instanceof Content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate guardControlsPhiInput(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::Definition def, IRBlock input, Ssa::PhiInputNodeExt phi
|
||||||
|
) {
|
||||||
|
phi.hasInputFromBlock(def, input) and
|
||||||
|
(
|
||||||
|
g.controls(input, branch)
|
||||||
|
or
|
||||||
|
exists(EdgeKind kind |
|
||||||
|
g.getBlock() = input and
|
||||||
|
kind = getConditionalEdge(branch) and
|
||||||
|
input.getSuccessor(kind) = phi.getBasicBlock()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||||
*
|
*
|
||||||
@@ -2721,13 +2743,22 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
ExprNode getABarrierNode() {
|
Node getABarrierNode() {
|
||||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||||
result.getConvertedExpr() = e and
|
result.asConvertedExpr() = e and
|
||||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||||
g.controls(result.getBasicBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
|
||||||
|
Ssa::PhiInputNodeExt phi
|
||||||
|
|
|
||||||
|
guardChecks(g, def.getARead().asOperand().getDef().getConvertedResultExpression(), branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi.getPhi(), input)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2763,7 +2794,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
||||||
@@ -2799,13 +2830,24 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*
|
*
|
||||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||||
*/
|
*/
|
||||||
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
|
Node getAnIndirectBarrierNode(int indirectionIndex) {
|
||||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||||
result.getConvertedExpr(indirectionIndex) = e and
|
result.asIndirectConvertedExpr(indirectionIndex) = e and
|
||||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||||
g.controls(result.getBasicBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
|
||||||
|
Ssa::PhiInputNodeExt phi
|
||||||
|
|
|
||||||
|
guardChecks(g,
|
||||||
|
def.getARead().asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
|
||||||
|
branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi.getPhi(), input)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2814,6 +2856,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
*/
|
*/
|
||||||
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
||||||
|
|
||||||
|
private EdgeKind getConditionalEdge(boolean branch) {
|
||||||
|
branch = true and
|
||||||
|
result instanceof TrueEdge
|
||||||
|
or
|
||||||
|
branch = false and
|
||||||
|
result instanceof FalseEdge
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a set of barrier nodes for a guard that validates an instruction.
|
* Provides a set of barrier nodes for a guard that validates an instruction.
|
||||||
*
|
*
|
||||||
@@ -2822,12 +2872,21 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
|
|||||||
*/
|
*/
|
||||||
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
||||||
/** Gets a node that is safely guarded by the given guard check. */
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
ExprNode getABarrierNode() {
|
Node getABarrierNode() {
|
||||||
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
|
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
|
||||||
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
||||||
use = value.getAnInstruction().getAUse() and
|
use = value.getAnInstruction().getAUse() and
|
||||||
result.asOperand() = use and
|
result.asOperand() = use and
|
||||||
g.controls(use.getDef().getBlock(), edge)
|
g.controls(result.getBasicBlock(), edge)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input,
|
||||||
|
Ssa::PhiInputNodeExt phi
|
||||||
|
|
|
||||||
|
instructionGuardChecks(g, def.getARead().asOperand().getDef(), branch) and
|
||||||
|
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||||
|
result = TSsaPhiInputNode(phi.getPhi(), input)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user