Skip to content

Commit ef331ee

Browse files
authored
Merge pull request #633 from Semmle/rdmarsh/cpp/range-analysis
C++: New range analysis
2 parents c8cbc8e + c455db9 commit ef331ee

File tree

30 files changed

+1171
-72
lines changed

30 files changed

+1171
-72
lines changed

cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,32 @@ class IRGuardCondition extends Instruction {
280280
ne.controls(controlled, testIsTrue.booleanNot()))
281281
}
282282

283+
/**
284+
* Holds if `branch` jumps directly to `succ` when this condition is `testIsTrue`.
285+
*
286+
* This predicate is intended to help with situations in which an inference can only be made
287+
* based on an edge between a block with multiple successors and a block with multiple
288+
* predecessors. For example, in the following situation, an inference can be made about the
289+
* value of `x` at the end of the `if` statement, but there is no block which is controlled by
290+
* the `if` statement when `x >= y`.
291+
* ```
292+
* if (x < y) {
293+
* x = y;
294+
* }
295+
* return x;
296+
* ```
297+
*/
298+
predicate hasBranchEdge(ConditionalBranchInstruction branch, IRBlock succ, boolean testIsTrue) {
299+
branch.getCondition() = this and
300+
(
301+
testIsTrue = true and
302+
succ.getFirstInstruction() = branch.getTrueSuccessor()
303+
or
304+
testIsTrue = false and
305+
succ.getFirstInstruction() = branch.getFalseSuccessor()
306+
)
307+
}
308+
283309
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
284310
cached predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) {
285311
compares_lt(this, left, right, k, isLessThan, testIsTrue)

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ module InstructionSanity {
130130
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
131131
blockCount = count(instr.getBlock()) and
132132
blockCount != 1
133-
}
133+
}
134134
}
135135

136136
/**
@@ -750,6 +750,15 @@ class BinaryInstruction extends Instruction {
750750
final Instruction getRightOperand() {
751751
result = getAnOperand().(RightOperand).getDefinitionInstruction()
752752
}
753+
754+
/**
755+
* Holds if this instruction's operands are `op1` and `op2`, in either order.
756+
*/
757+
final predicate hasOperands(Operand op1, Operand op2) {
758+
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
759+
or
760+
op1 = getAnOperand().(RightOperand) and op2 = getAnOperand().(LeftOperand)
761+
}
753762
}
754763

755764
class AddInstruction extends BinaryInstruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class Operand extends TOperand {
2121
result = "Operand"
2222
}
2323

24+
Location getLocation() {
25+
result = getInstruction().getLocation()
26+
}
27+
2428
/**
2529
* Gets the `Instruction` that consumes this operand.
2630
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ class ValueNumber extends TValueNumber {
8383
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
8484
)
8585
}
86+
87+
final Operand getAUse() {
88+
this = valueNumber(result.getDefinitionInstruction())
89+
}
8690
}
8791

8892
/**
@@ -107,6 +111,7 @@ private class CongruentCopyInstruction extends CopyInstruction {
107111
def = this.getSourceValue() and
108112
(
109113
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
114+
def.getResultMemoryAccess() instanceof PhiMemoryAccess or
110115
not def.hasMemoryResult()
111116
)
112117
)
@@ -211,14 +216,21 @@ private predicate uniqueValueNumber(Instruction instr, FunctionIR funcIR) {
211216
/**
212217
* Gets the value number assigned to `instr`, if any. Returns at most one result.
213218
*/
214-
ValueNumber valueNumber(Instruction instr) {
219+
cached ValueNumber valueNumber(Instruction instr) {
215220
result = nonUniqueValueNumber(instr) or
216221
exists(FunctionIR funcIR |
217222
uniqueValueNumber(instr, funcIR) and
218223
result = TUniqueValueNumber(funcIR, instr)
219224
)
220225
}
221226

227+
/**
228+
* Gets the value number assigned to `instr`, if any. Returns at most one result.
229+
*/
230+
ValueNumber valueNumberOfOperand(Operand op) {
231+
result = valueNumber(op.getDefinitionInstruction())
232+
}
233+
222234
/**
223235
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
224236
* value number.

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ module InstructionSanity {
130130
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
131131
blockCount = count(instr.getBlock()) and
132132
blockCount != 1
133-
}
133+
}
134134
}
135135

136136
/**
@@ -750,6 +750,12 @@ class BinaryInstruction extends Instruction {
750750
final Instruction getRightOperand() {
751751
result = getAnOperand().(RightOperand).getDefinitionInstruction()
752752
}
753+
754+
final predicate hasOperands(Operand op1, Operand op2) {
755+
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
756+
or
757+
op1 = getAnOperand().(RightOperand) and op2 = getAnOperand().(LeftOperand)
758+
}
753759
}
754760

755761
class AddInstruction extends BinaryInstruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class Operand extends TOperand {
2121
result = "Operand"
2222
}
2323

24+
Location getLocation() {
25+
result = getInstruction().getLocation()
26+
}
27+
2428
/**
2529
* Gets the `Instruction` that consumes this operand.
2630
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ private class CongruentCopyInstruction extends CopyInstruction {
107107
def = this.getSourceValue() and
108108
(
109109
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
110+
def.getResultMemoryAccess() instanceof PhiMemoryAccess or
110111
not def.hasMemoryResult()
111112
)
112113
)

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ module InstructionSanity {
130130
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
131131
blockCount = count(instr.getBlock()) and
132132
blockCount != 1
133-
}
133+
}
134134
}
135135

136136
/**
@@ -750,6 +750,12 @@ class BinaryInstruction extends Instruction {
750750
final Instruction getRightOperand() {
751751
result = getAnOperand().(RightOperand).getDefinitionInstruction()
752752
}
753+
754+
final predicate hasOperands(Operand op1, Operand op2) {
755+
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
756+
or
757+
op1 = getAnOperand().(RightOperand) and op2 = getAnOperand().(LeftOperand)
758+
}
753759
}
754760

755761
class AddInstruction extends BinaryInstruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class Operand extends TOperand {
2121
result = "Operand"
2222
}
2323

24+
Location getLocation() {
25+
result = getInstruction().getLocation()
26+
}
27+
2428
/**
2529
* Gets the `Instruction` that consumes this operand.
2630
*/

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ private class CongruentCopyInstruction extends CopyInstruction {
107107
def = this.getSourceValue() and
108108
(
109109
def.getResultMemoryAccess() instanceof IndirectMemoryAccess or
110+
def.getResultMemoryAccess() instanceof PhiMemoryAccess or
110111
not def.hasMemoryResult()
111112
)
112113
)

0 commit comments

Comments
 (0)