mirror of
https://github.com/github/codeql.git
synced 2025-12-23 20:26:32 +01:00
C++: Add guards logic for constant comparisons.
This commit is contained in:
@@ -452,6 +452,21 @@ class IRGuardCondition extends Instruction {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||||
|
cached
|
||||||
|
predicate comparesEq(Operand op, int k, boolean areEqual, boolean testIsTrue) {
|
||||||
|
exists(MatchValue mv |
|
||||||
|
compares_eq(this, op, k, areEqual, mv) and
|
||||||
|
// A match value cannot be dualized, so `testIsTrue` is always true
|
||||||
|
testIsTrue = true
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(BooleanValue bv |
|
||||||
|
compares_eq(this, op, k, areEqual, bv) and
|
||||||
|
bv.getValue() = testIsTrue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
|
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
|
||||||
* If `areEqual = false` then this implies `left != right + k`.
|
* If `areEqual = false` then this implies `left != right + k`.
|
||||||
@@ -463,6 +478,17 @@ class IRGuardCondition extends Instruction {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `op == k` must be `areEqual` in `block`.
|
||||||
|
* If `areEqual = false` then this implies `op != k`.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
|
||||||
|
exists(AbstractValue value |
|
||||||
|
compares_eq(this, op, k, areEqual, value) and this.valueControls(block, value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from
|
* 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`.
|
* `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`.
|
||||||
@@ -477,6 +503,18 @@ class IRGuardCondition extends Instruction {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if (determined by this guard) `op == k` must be `areEqual` on the edge from
|
||||||
|
* `pred` to `succ`. If `areEqual = false` then this implies `op != k`.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
|
||||||
|
exists(AbstractValue value |
|
||||||
|
compares_eq(this, op, k, areEqual, value) and
|
||||||
|
this.valueControlsEdge(pred, succ, value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this condition controls `block`, meaning that `block` is only
|
* Holds if this condition controls `block`, meaning that `block` is only
|
||||||
* entered if the value of this condition is `v`. This helper
|
* entered if the value of this condition is `v`. This helper
|
||||||
@@ -598,6 +636,33 @@ private predicate compares_eq(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if `op == k` is `areEqual` given that `test` is equal to `value`. */
|
||||||
|
private predicate compares_eq(
|
||||||
|
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||||
|
) {
|
||||||
|
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||||
|
exists(AbstractValue v | simple_comparison_eq(test, op, k, v) |
|
||||||
|
areEqual = true and value = v
|
||||||
|
or
|
||||||
|
areEqual = false and value = v.getDualValue()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
complex_eq(test, op, k, areEqual, value)
|
||||||
|
or
|
||||||
|
/* (x is true => (op == k)) => (!x is false => (op == k)) */
|
||||||
|
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||||
|
compares_eq(test.(LogicalNotInstruction).getUnary(), op, k, areEqual, dual)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
|
||||||
|
// test is `areEqual` => op == k1 + k2
|
||||||
|
exists(int k1, int k2, ConstantInstruction const |
|
||||||
|
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
|
||||||
|
int_value(const) = k1 and
|
||||||
|
k = k1 + k2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** Rearrange various simple comparisons into `left == right + k` form. */
|
/** Rearrange various simple comparisons into `left == right + k` form. */
|
||||||
private predicate simple_comparison_eq(
|
private predicate simple_comparison_eq(
|
||||||
CompareInstruction cmp, Operand left, Operand right, int k, AbstractValue value
|
CompareInstruction cmp, Operand left, Operand right, int k, AbstractValue value
|
||||||
@@ -615,6 +680,15 @@ private predicate simple_comparison_eq(
|
|||||||
value.(BooleanValue).getValue() = false
|
value.(BooleanValue).getValue() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Rearrange various simple comparisons into `op == k` form. */
|
||||||
|
private predicate simple_comparison_eq(Instruction test, Operand op, int k, AbstractValue value) {
|
||||||
|
exists(SwitchInstruction switch |
|
||||||
|
test = switch.getExpression() and
|
||||||
|
op.getDef() = test and
|
||||||
|
value.(MatchValue).getCase().getValue().toInt() = k
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate complex_eq(
|
private predicate complex_eq(
|
||||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||||
) {
|
) {
|
||||||
@@ -623,6 +697,14 @@ private predicate complex_eq(
|
|||||||
add_eq(cmp, left, right, k, areEqual, value)
|
add_eq(cmp, left, right, k, areEqual, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate complex_eq(
|
||||||
|
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||||
|
) {
|
||||||
|
sub_eq(test, op, k, areEqual, value)
|
||||||
|
or
|
||||||
|
add_eq(test, op, k, areEqual, value)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simplification of inequality expressions
|
* Simplification of inequality expressions
|
||||||
* Simplify conditions in the source to the canonical form l < r + k.
|
* Simplify conditions in the source to the canonical form l < r + k.
|
||||||
@@ -802,6 +884,23 @@ private predicate sub_eq(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// op - x == c => op == (c+x)
|
||||||
|
private predicate sub_eq(Instruction test, Operand op, int k, boolean areEqual, AbstractValue value) {
|
||||||
|
exists(SubInstruction sub, int c, int x |
|
||||||
|
compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||||
|
op = sub.getLeftOperand() and
|
||||||
|
x = int_value(sub.getRight()) and
|
||||||
|
k = c + x
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(PointerSubInstruction sub, int c, int x |
|
||||||
|
compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||||
|
op = sub.getLeftOperand() and
|
||||||
|
x = int_value(sub.getRight()) and
|
||||||
|
k = c + x
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// left + x == right + c => left == right + (c-x)
|
// left + x == right + c => left == right + (c-x)
|
||||||
// left == (right + x) + c => left == right + (c+x)
|
// left == (right + x) + c => left == right + (c+x)
|
||||||
private predicate add_eq(
|
private predicate add_eq(
|
||||||
@@ -848,5 +947,30 @@ private predicate add_eq(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// left + x == right + c => left == right + (c-x)
|
||||||
|
private predicate add_eq(
|
||||||
|
Instruction test, Operand left, int k, boolean areEqual, AbstractValue value
|
||||||
|
) {
|
||||||
|
exists(AddInstruction lhs, int c, int x |
|
||||||
|
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||||
|
(
|
||||||
|
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||||
|
or
|
||||||
|
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||||
|
) and
|
||||||
|
k = c - x
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(PointerAddInstruction lhs, int c, int x |
|
||||||
|
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||||
|
(
|
||||||
|
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||||
|
or
|
||||||
|
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||||
|
) and
|
||||||
|
k = c - x
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** The int value of integer constant expression. */
|
/** The int value of integer constant expression. */
|
||||||
private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() }
|
private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() }
|
||||||
|
|||||||
Reference in New Issue
Block a user