mirror of
https://github.com/github/codeql.git
synced 2025-12-17 09:13:20 +01:00
C++: respond to further PR comments
This commit is contained in:
@@ -295,7 +295,7 @@ class IRGuardCondition extends Instruction {
|
|||||||
* return x;
|
* return x;
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
predicate controlsEdgeDirectly(ConditionalBranchInstruction branch, IRBlock succ, boolean testIsTrue) {
|
predicate hasBranchEdge(ConditionalBranchInstruction branch, IRBlock succ, boolean testIsTrue) {
|
||||||
branch.getCondition() = this and
|
branch.getCondition() = this and
|
||||||
(
|
(
|
||||||
testIsTrue = true and
|
testIsTrue = true and
|
||||||
|
|||||||
@@ -751,6 +751,9 @@ class BinaryInstruction extends Instruction {
|
|||||||
result = getAnOperand().(RightOperand).getDefinitionInstruction()
|
result = getAnOperand().(RightOperand).getDefinitionInstruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this instruction's operands are `op1` and `op2`, in either order.
|
||||||
|
*/
|
||||||
final predicate hasOperands(Operand op1, Operand op2) {
|
final predicate hasOperands(Operand op1, Operand op2) {
|
||||||
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
|
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ class ValueNumber extends TValueNumber {
|
|||||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Operand getAUse() {
|
||||||
|
this = valueNumber(result.getDefinitionInstruction())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -220,6 +224,13 @@ ValueNumber valueNumber(Instruction instr) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value number assigned to `instr`, if any. Returns at most one result.
|
||||||
|
*/
|
||||||
|
ValueNumber valueNumberOfOperand(Operand op) {
|
||||||
|
result = valueNumber(op.getDefinitionInstruction())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
|
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
|
||||||
* value number.
|
* value number.
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ private newtype TBound =
|
|||||||
TBoundInstruction(Instruction i) {
|
TBoundInstruction(Instruction i) {
|
||||||
i.getResultType() instanceof IntegralType or
|
i.getResultType() instanceof IntegralType or
|
||||||
i.getResultType() instanceof PointerType
|
i.getResultType() instanceof PointerType
|
||||||
} or
|
|
||||||
TBoundOperand(Operand o) {
|
|
||||||
o.getDefinitionInstruction().getResultType() instanceof IntegralType or
|
|
||||||
o.getDefinitionInstruction().getResultType() instanceof PointerType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,23 +49,3 @@ class InstructionBound extends Bound, TBoundInstruction {
|
|||||||
getInstruction().getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
getInstruction().getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A bound corresponding to the value of an `Operand`.
|
|
||||||
*/
|
|
||||||
class OperandBound extends Bound, TBoundOperand {
|
|
||||||
Operand getOperand() {
|
|
||||||
this = TBoundOperand(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
override Instruction getInstruction(int delta) {
|
|
||||||
this = TBoundOperand(result.getAUse()) and
|
|
||||||
delta = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override string toString() { result = getOperand().toString() }
|
|
||||||
|
|
||||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
|
||||||
getOperand().getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -124,14 +124,10 @@ import RangeAnalysisPublic
|
|||||||
* - `isEq = true` : `i == bound + delta`
|
* - `isEq = true` : `i == bound + delta`
|
||||||
* - `isEq = false` : `i != bound + delta`
|
* - `isEq = false` : `i != bound + delta`
|
||||||
*/
|
*/
|
||||||
private IRGuardCondition eqFlowCond(Operand op, Operand bound, int delta,
|
private IRGuardCondition eqFlowCond(ValueNumber vn, Operand bound, int delta,
|
||||||
boolean isEq, boolean testIsTrue)
|
boolean isEq, boolean testIsTrue)
|
||||||
{
|
{
|
||||||
exists(Operand compared |
|
result.comparesEq(vn.getAUse(), bound, delta, isEq, testIsTrue)
|
||||||
result.ensuresEq(compared, bound, delta, op.getInstruction().getBlock(), isEq) and
|
|
||||||
result.controls(bound.getInstruction().getBlock(), testIsTrue) and
|
|
||||||
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,8 +143,9 @@ private predicate boundFlowStepSsa(
|
|||||||
reason = TNoReason() and
|
reason = TNoReason() and
|
||||||
delta = 0
|
delta = 0
|
||||||
or*/
|
or*/
|
||||||
exists(IRGuardCondition guard |
|
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||||
guard = boundFlowCond(op2, op1, delta, upper, _) and
|
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||||
|
guard.controls(op2.getInstruction().getBlock(), testIsTrue) and
|
||||||
reason = TCondReason(guard)
|
reason = TCondReason(guard)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -160,37 +157,19 @@ private predicate boundFlowStepSsa(
|
|||||||
* - `upper = true` : `op <= bound + delta`
|
* - `upper = true` : `op <= bound + delta`
|
||||||
* - `upper = false` : `op >= bound + delta`
|
* - `upper = false` : `op >= bound + delta`
|
||||||
*/
|
*/
|
||||||
private IRGuardCondition boundFlowCond(NonPhiOperand op, NonPhiOperand bound, int delta, boolean upper,
|
private IRGuardCondition boundFlowCond(ValueNumber vn, NonPhiOperand bound, int delta, boolean upper,
|
||||||
boolean testIsTrue)
|
boolean testIsTrue)
|
||||||
{
|
{
|
||||||
exists(Operand compared |
|
exists(int d |
|
||||||
result.comparesLt(compared, bound, delta, upper, testIsTrue) and
|
result.comparesLt(vn.getAUse(), bound, d, upper, testIsTrue) and
|
||||||
result.controls(op.getInstruction().getBlock(), testIsTrue) and
|
// strengthen from x < y to x <= y-1
|
||||||
valueNumber(compared.getDefinitionInstruction()) = valueNumber(op.getDefinitionInstruction())
|
if upper = true
|
||||||
)
|
then delta = d-1
|
||||||
// TODO: strengthening through modulus library
|
else delta = d
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a condition that tests whether `op` is bounded by `bound + delta`.
|
|
||||||
*
|
|
||||||
* - `upper = true` : `op <= bound + delta`
|
|
||||||
* - `upper = false` : `op >= bound + delta`
|
|
||||||
*/
|
|
||||||
private IRGuardCondition boundFlowCondPhi(PhiOperand op, NonPhiOperand bound, int delta, boolean upper,
|
|
||||||
boolean testIsTrue)
|
|
||||||
{
|
|
||||||
exists(Operand compared |
|
|
||||||
result.comparesLt(compared, bound, delta, upper, testIsTrue) and
|
|
||||||
result.controlsEdgeDirectly(op.getPredecessorBlock().getLastInstruction(), op.getInstruction().getBlock(), testIsTrue) and
|
|
||||||
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Operand compared |
|
result = eqFlowCond(vn, bound, delta, true, testIsTrue) and
|
||||||
result.comparesLt(compared, bound, delta, upper, testIsTrue) and
|
(upper = true or upper = false)
|
||||||
result.controls(op.getPredecessorBlock(), testIsTrue) and
|
|
||||||
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
|
|
||||||
)
|
|
||||||
// TODO: strengthening through modulus library
|
// TODO: strengthening through modulus library
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +218,9 @@ private predicate safeCast(IntegralType fromtyp, IntegralType totyp) {
|
|||||||
private class SafeCastInstruction extends ConvertInstruction {
|
private class SafeCastInstruction extends ConvertInstruction {
|
||||||
SafeCastInstruction() {
|
SafeCastInstruction() {
|
||||||
safeCast(getResultType(), getOperand().getResultType())
|
safeCast(getResultType(), getOperand().getResultType())
|
||||||
|
or
|
||||||
|
getResultType() instanceof PointerType and
|
||||||
|
getOperand().getResultType() instanceof PointerType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,8 +384,13 @@ private predicate boundFlowStepPhi(
|
|||||||
reason = TNoReason() and
|
reason = TNoReason() and
|
||||||
delta = 0
|
delta = 0
|
||||||
or
|
or
|
||||||
exists(IRGuardCondition guard |
|
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||||
guard = boundFlowCondPhi(op2, op1, delta, upper, _) and
|
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||||
|
(
|
||||||
|
guard.hasBranchEdge(op2.getPredecessorBlock().getLastInstruction(), op2.getInstruction().getBlock(), testIsTrue)
|
||||||
|
or
|
||||||
|
guard.controls(op2.getPredecessorBlock(), testIsTrue)
|
||||||
|
) and
|
||||||
reason = TCondReason(guard)
|
reason = TCondReason(guard)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -476,8 +463,6 @@ private predicate boundedPhiInp(
|
|||||||
) {
|
) {
|
||||||
phi.getAnOperand() = op and
|
phi.getAnOperand() = op and
|
||||||
exists(int d, boolean fromBackEdge0 |
|
exists(int d, boolean fromBackEdge0 |
|
||||||
boundedInstruction(op.getDefinitionInstruction(), b, d, upper, fromBackEdge0, origdelta, reason)
|
|
||||||
or
|
|
||||||
boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason)
|
boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason)
|
||||||
or
|
or
|
||||||
b.(InstructionBound).getInstruction() = op.getDefinitionInstruction() and
|
b.(InstructionBound).getInstruction() = op.getDefinitionInstruction() and
|
||||||
@@ -564,6 +549,7 @@ private predicate boundedInstruction(
|
|||||||
boundedPhiCandValidForEdge(i, b, delta, upper, fromBackEdge, origdelta, reason, op)
|
boundedPhiCandValidForEdge(i, b, delta, upper, fromBackEdge, origdelta, reason, op)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
not i instanceof PhiInstruction and
|
||||||
i = b.getInstruction(delta) and
|
i = b.getInstruction(delta) and
|
||||||
(upper = true or upper = false) and
|
(upper = true or upper = false) and
|
||||||
fromBackEdge = false and
|
fromBackEdge = false and
|
||||||
|
|||||||
@@ -44,4 +44,21 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) {
|
|||||||
|
|
|
|
||||||
delta = -getValue(getConstantValue(x.getDefinitionInstruction()))
|
delta = -getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(Operand x |
|
||||||
|
i.(PointerAddInstruction).getAnOperand() = op and
|
||||||
|
i.(PointerAddInstruction).getAnOperand() = x and
|
||||||
|
op != x
|
||||||
|
|
|
||||||
|
delta = i.(PointerAddInstruction).getElementSize() *
|
||||||
|
getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Operand x |
|
||||||
|
i.(PointerSubInstruction).getAnOperand().(LeftOperand) = op and
|
||||||
|
i.(PointerSubInstruction).getAnOperand().(RightOperand) = x
|
||||||
|
|
|
||||||
|
delta = i.(PointerSubInstruction).getElementSize() *
|
||||||
|
-getValue(getConstantValue(x.getDefinitionInstruction()))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,39 @@
|
|||||||
| test.cpp:8:9:8:9 | Load: y | test.cpp:6:15:6:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... |
|
| test.cpp:10:10:10:10 | Store: x | test.cpp:6:15:6:15 | InitializeParameter: x | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:15:6:15 | InitializeParameter: x | 0 | false | NoReason |
|
| test.cpp:10:10:10:10 | Store: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... | test.cpp:7:7:7:11 | test.cpp:7:7:7:11 |
|
||||||
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... |
|
| test.cpp:10:10:10:10 | Store: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | NoReason |
|
| test.cpp:20:10:20:10 | Store: x | test.cpp:14:15:14:15 | InitializeParameter: x | -2 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
| test.cpp:16:9:16:9 | Load: y | test.cpp:14:15:14:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... |
|
| test.cpp:20:10:20:10 | Store: x | test.cpp:14:22:14:22 | InitializeParameter: y | -2 | false | CompareLT: ... < ... | test.cpp:15:7:15:11 | test.cpp:15:7:15:11 |
|
||||||
| test.cpp:18:9:18:9 | Load: x | test.cpp:14:22:14:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... |
|
| test.cpp:27:10:27:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
| test.cpp:20:10:20:10 | Load: x | test.cpp:14:15:14:15 | InitializeParameter: x | -2 | false | NoReason |
|
| test.cpp:27:10:27:10 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | -1 | true | CompareLT: ... < ... | test.cpp:26:14:26:18 | test.cpp:26:14:26:18 |
|
||||||
| test.cpp:20:10:20:10 | Load: x | test.cpp:14:22:14:22 | InitializeParameter: y | -2 | false | CompareLT: ... < ... |
|
| test.cpp:27:10:27:10 | Load: i | test.cpp:26:18:26:18 | Load: x | -1 | true | CompareLT: ... < ... | test.cpp:26:14:26:18 | test.cpp:26:14:26:18 |
|
||||||
| test.cpp:26:14:26:14 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason |
|
| test.cpp:30:10:30:10 | Load: i | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... | test.cpp:29:14:29:18 | test.cpp:29:14:29:18 |
|
||||||
| test.cpp:26:21:26:23 | Load: ... ++ | file://:0:0:0:0 | 0 | 0 | false | NoReason |
|
| test.cpp:30:10:30:10 | Load: i | test.cpp:29:18:29:18 | Constant: 0 | 1 | false | CompareGT: ... > ... | test.cpp:29:14:29:18 | test.cpp:29:14:29:18 |
|
||||||
| test.cpp:26:21:26:23 | Load: ... ++ | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | CompareLT: ... < ... |
|
| test.cpp:33:10:33:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
| test.cpp:27:7:27:7 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason |
|
| test.cpp:33:10:33:10 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
|
||||||
| test.cpp:27:7:27:7 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | CompareLT: ... < ... |
|
| test.cpp:33:10:33:10 | Load: i | test.cpp:26:14:26:14 | Load: i | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
|
||||||
| test.cpp:29:14:29:14 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason |
|
| test.cpp:33:10:33:10 | Load: i | test.cpp:32:18:32:18 | Load: x | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
|
||||||
| test.cpp:29:21:29:23 | Load: ... -- | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... |
|
| test.cpp:33:10:33:10 | Load: i | test.cpp:32:18:32:22 | Add: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
|
||||||
| test.cpp:29:21:29:23 | Load: ... -- | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason |
|
| test.cpp:40:10:40:14 | Load: begin | test.cpp:38:28:38:30 | InitializeParameter: end | -1 | true | CompareLT: ... < ... | test.cpp:39:10:39:20 | test.cpp:39:10:39:20 |
|
||||||
| test.cpp:30:7:30:7 | Load: i | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... |
|
| test.cpp:40:10:40:14 | Load: begin | test.cpp:39:18:39:20 | Load: end | -1 | true | CompareLT: ... < ... | test.cpp:39:10:39:20 | test.cpp:39:10:39:20 |
|
||||||
| test.cpp:30:7:30:7 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason |
|
| test.cpp:49:12:49:12 | Load: x | test.cpp:46:22:46:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
|
||||||
| test.cpp:37:6:37:10 | Load: begin | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... |
|
| test.cpp:49:12:49:12 | Load: x | test.cpp:46:29:46:29 | InitializeParameter: z | -2 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
|
||||||
| test.cpp:37:16:37:20 | Load: begin | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... |
|
| test.cpp:49:12:49:12 | Load: x | test.cpp:47:11:47:11 | Load: z | -2 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
|
||||||
| test.cpp:38:5:38:11 | Load: ... ++ | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... |
|
| test.cpp:49:12:49:12 | Load: x | test.cpp:48:13:48:13 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
|
||||||
| test.cpp:44:13:44:13 | Load: y | test.cpp:42:29:42:29 | InitializeParameter: z | 0 | true | CompareLT: ... < ... |
|
| test.cpp:54:12:54:12 | Load: x | test.cpp:46:22:46:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:52:7:52:11 | test.cpp:52:7:52:11 |
|
||||||
| test.cpp:45:12:45:12 | Load: x | test.cpp:42:22:42:22 | InitializeParameter: y | 0 | true | CompareLT: ... < ... |
|
| test.cpp:54:12:54:12 | Load: x | test.cpp:52:11:52:11 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:52:7:52:11 | test.cpp:52:7:52:11 |
|
||||||
| test.cpp:45:12:45:12 | Load: x | test.cpp:42:29:42:29 | InitializeParameter: z | 0 | true | CompareLT: ... < ... |
|
| test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | InitializeParameter: p | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
|
||||||
| test.cpp:49:9:49:9 | Load: y | test.cpp:42:15:42:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... |
|
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:39:61:51 | Convert: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
|
||||||
| test.cpp:50:12:50:12 | Load: x | test.cpp:42:22:42:22 | InitializeParameter: y | 0 | true | CompareLT: ... < ... |
|
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:48 | Load: p | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
|
||||||
|
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:50 | PointerAdd: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | InitializeParameter: p | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:32:61:35 | Load: iter | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:15:65:27 | Convert: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:15:65:27 | Store: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:24:65:24 | Load: p | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:24:65:26 | PointerAdd: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:67:10:67:13 | Load: iter | test.cpp:66:39:66:41 | Load: end | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
|
||||||
|
| test.cpp:77:12:77:12 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||||
|
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:15:72:15 | InitializeParameter: x | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
|
||||||
|
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:22:72:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
|
||||||
|
| test.cpp:77:12:77:12 | Load: i | test.cpp:75:7:75:7 | Load: x | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
|
||||||
|
| test.cpp:77:12:77:12 | Load: i | test.cpp:76:24:76:24 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
|
||||||
|
|||||||
@@ -3,14 +3,23 @@ import semmle.code.cpp.ir.IR
|
|||||||
import semmle.code.cpp.controlflow.IRGuards
|
import semmle.code.cpp.controlflow.IRGuards
|
||||||
import semmle.code.cpp.ir.ValueNumbering
|
import semmle.code.cpp.ir.ValueNumbering
|
||||||
|
|
||||||
query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upper, Reason reason)
|
query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upper, Reason reason,
|
||||||
|
Location reasonLoc)
|
||||||
{
|
{
|
||||||
i instanceof LoadInstruction and
|
|
||||||
boundedInstruction(i, b, delta, upper, reason) and
|
|
||||||
(
|
(
|
||||||
b.(InstructionBound).getInstruction() instanceof InitializeParameterInstruction or
|
i.getAUse() instanceof ArgumentOperand
|
||||||
b.(InstructionBound).getInstruction() instanceof CallInstruction or
|
or
|
||||||
b instanceof ZeroBound
|
i.getAUse() instanceof ReturnValueOperand
|
||||||
) and
|
) and
|
||||||
not valueNumber(b.(InstructionBound).getInstruction()) = valueNumber(i)
|
(
|
||||||
|
upper = true and
|
||||||
|
delta = min(int d | boundedInstruction(i, b, d, upper, reason))
|
||||||
|
or
|
||||||
|
upper = false and
|
||||||
|
delta = max(int d | boundedInstruction(i, b, d, upper, reason))
|
||||||
|
) and
|
||||||
|
not valueNumber(b.getInstruction()) = valueNumber(i)
|
||||||
|
and if reason instanceof CondReason
|
||||||
|
then reasonLoc = reason.(CondReason).getCond().getLocation()
|
||||||
|
else reasonLoc instanceof UnknownDefaultLocation
|
||||||
}
|
}
|
||||||
@@ -21,24 +21,28 @@ int test2(int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for loops
|
// for loops
|
||||||
int test3(int x, int *p) {
|
int test3(int x) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < x; i++) {
|
for(i = 0; i < x; i++) {
|
||||||
p[i];
|
sink(i);
|
||||||
}
|
}
|
||||||
for(i = x; i > 0; i--) {
|
for(i = x; i > 0; i--) {
|
||||||
p[i];
|
sink(i);
|
||||||
|
}
|
||||||
|
for(i = 0; i < x + 2; i++) {
|
||||||
|
sink(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointer bounds
|
// pointer bounds
|
||||||
int test4(int *begin, int *end) {
|
int test4(int *begin, int *end) {
|
||||||
while (begin < end) {
|
while (begin < end) {
|
||||||
*begin = (*begin) + 1;
|
sink(begin);
|
||||||
begin++;
|
begin++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bound propagation through conditionals
|
||||||
int test5(int x, int y, int z) {
|
int test5(int x, int y, int z) {
|
||||||
if (y < z) {
|
if (y < z) {
|
||||||
if (x < y) {
|
if (x < y) {
|
||||||
@@ -51,3 +55,26 @@ int test5(int x, int y, int z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointer arithmetic and sizes
|
||||||
|
void test6(int *p) {
|
||||||
|
for (char *iter = (char *)p; iter < (char *)(p+1); iter++) {
|
||||||
|
sink(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *end = (char *)(p+1);
|
||||||
|
for (char *iter = (char *)p; iter < end; iter++) {
|
||||||
|
sink(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inference from equality
|
||||||
|
int test8(int x, int y) {
|
||||||
|
int *p = new int[x];
|
||||||
|
|
||||||
|
if (x == y) {
|
||||||
|
for(int i = 0; i < y; ++i) {
|
||||||
|
sink(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user