mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
C++: Lift a few more predicates to expression guards.
This commit is contained in:
@@ -72,6 +72,20 @@ abstract private class GuardConditionImpl extends Expr {
|
|||||||
*/
|
*/
|
||||||
abstract predicate valueControls(BasicBlock controlled, AbstractValue v);
|
abstract predicate valueControls(BasicBlock controlled, AbstractValue v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the control-flow edge `(pred, succ)` may be taken only if
|
||||||
|
* the value of this condition is `v`.
|
||||||
|
*/
|
||||||
|
abstract predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the control-flow edge `(pred, succ)` may be taken only if
|
||||||
|
* this the value of this condition is `testIsTrue`.
|
||||||
|
*/
|
||||||
|
final predicate controlsEdge(BasicBlock pred, BasicBlock succ, boolean testIsTrue) {
|
||||||
|
this.valueControlsEdge(pred, succ, any(BooleanValue bv | bv.getValue() = testIsTrue))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
||||||
* entered if the value of this condition is `testIsTrue`.
|
* entered if the value of this condition is `testIsTrue`.
|
||||||
@@ -175,6 +189,58 @@ abstract private class GuardConditionImpl extends Expr {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
abstract predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual);
|
abstract predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from
|
||||||
|
* `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`.
|
||||||
|
*/
|
||||||
|
pragma[inline]
|
||||||
|
final predicate ensuresEqEdge(
|
||||||
|
Expr left, Expr right, int k, BasicBlock pred, BasicBlock succ, boolean areEqual
|
||||||
|
) {
|
||||||
|
exists(boolean testIsTrue |
|
||||||
|
this.comparesEq(left, right, k, areEqual, testIsTrue) and
|
||||||
|
this.controlsEdge(pred, succ, testIsTrue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `e == k` must be `areEqual` on the edge from
|
||||||
|
* `pred` to `succ`. If `areEqual = false` then this implies `e != k`.
|
||||||
|
*/
|
||||||
|
pragma[inline]
|
||||||
|
final predicate ensuresEqEdge(Expr e, int k, BasicBlock pred, BasicBlock succ, boolean areEqual) {
|
||||||
|
exists(AbstractValue v |
|
||||||
|
this.comparesEq(e, k, areEqual, v) and
|
||||||
|
this.valueControlsEdge(pred, succ, v)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
|
||||||
|
* `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`.
|
||||||
|
*/
|
||||||
|
pragma[inline]
|
||||||
|
final predicate ensuresLtEdge(
|
||||||
|
Expr left, Expr right, int k, BasicBlock pred, BasicBlock succ, boolean isLessThan
|
||||||
|
) {
|
||||||
|
exists(boolean testIsTrue |
|
||||||
|
this.comparesLt(left, right, k, isLessThan, testIsTrue) and
|
||||||
|
this.controlsEdge(pred, succ, testIsTrue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `e < k` must be `isLessThan` on the edge from
|
||||||
|
* `pred` to `succ`. If `isLessThan = false` then this implies `e >= k`.
|
||||||
|
*/
|
||||||
|
pragma[inline]
|
||||||
|
final predicate ensuresLtEdge(Expr e, int k, BasicBlock pred, BasicBlock succ, boolean isLessThan) {
|
||||||
|
exists(AbstractValue v |
|
||||||
|
this.comparesEq(e, k, isLessThan, v) and
|
||||||
|
this.valueControlsEdge(pred, succ, v)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class GuardCondition = GuardConditionImpl;
|
final class GuardCondition = GuardConditionImpl;
|
||||||
@@ -187,6 +253,16 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
|
|||||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
|
||||||
|
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
|
||||||
|
this = binop and
|
||||||
|
lhs = binop.getLeftOperand() and
|
||||||
|
rhs = binop.getRightOperand() and
|
||||||
|
lhs.valueControlsEdge(pred, succ, v) and
|
||||||
|
rhs.valueControlsEdge(pred, succ, v)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
||||||
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
|
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
|
||||||
this = binop and
|
this = binop and
|
||||||
@@ -274,6 +350,25 @@ private predicate controlsBlock(IRGuardCondition ir, BasicBlock controlled, Abst
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `ir` controls the `(pred, succ)` edge, meaning that the edge
|
||||||
|
* `(pred, succ)` is only taken if the value of this condition is `v`. This
|
||||||
|
* helper predicate does not necessarily hold for binary logical operations
|
||||||
|
* like `&&` and `||`.
|
||||||
|
* See the detailed explanation on predicate `controlsEdge`.
|
||||||
|
*/
|
||||||
|
private predicate controlsEdge(
|
||||||
|
IRGuardCondition ir, BasicBlock pred, BasicBlock succ, AbstractValue v
|
||||||
|
) {
|
||||||
|
exists(IRBlock irPred, IRBlock irSucc |
|
||||||
|
ir.valueControlsEdge(irPred, irSucc, v) and
|
||||||
|
nonExcludedIRAndBasicBlock(irPred, pred) and
|
||||||
|
nonExcludedIRAndBasicBlock(irSucc, succ) and
|
||||||
|
not isUnreachedBlock(irPred) and
|
||||||
|
not isUnreachedBlock(irSucc)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private class GuardConditionFromNotExpr extends GuardConditionImpl {
|
private class GuardConditionFromNotExpr extends GuardConditionImpl {
|
||||||
IRGuardCondition ir;
|
IRGuardCondition ir;
|
||||||
|
|
||||||
@@ -295,6 +390,10 @@ private class GuardConditionFromNotExpr extends GuardConditionImpl {
|
|||||||
controlsBlock(ir, controlled, v.getDualValue())
|
controlsBlock(ir, controlled, v.getDualValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
|
||||||
|
controlsEdge(ir, pred, succ, v.getDualValue())
|
||||||
|
}
|
||||||
|
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||||
exists(Instruction li, Instruction ri |
|
exists(Instruction li, Instruction ri |
|
||||||
@@ -383,6 +482,10 @@ private class GuardConditionFromIR extends GuardConditionImpl {
|
|||||||
controlsBlock(ir, controlled, v)
|
controlsBlock(ir, controlled, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
|
||||||
|
controlsEdge(ir, pred, succ, v)
|
||||||
|
}
|
||||||
|
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||||
exists(Instruction li, Instruction ri |
|
exists(Instruction li, Instruction ri |
|
||||||
|
|||||||
Reference in New Issue
Block a user