C++: Add IntegerPartial, use in ConstantAnalysis

This adds `IntegerPartial.qll`, which is similar to
`IntegerConstant.qll` except that it contains partial functions on
integers instead of total functions on optional integers. This speeds up
the constant analysis so it takes 6.5s instead of 10.3s on comdb2.
This commit is contained in:
Jonas Jensen
2019-02-04 19:27:12 +01:00
parent 06ae0c421a
commit d66578eaa8
6 changed files with 148 additions and 16 deletions

View File

@@ -1,11 +1,11 @@
private import internal.ConstantAnalysisInternal
import semmle.code.cpp.ir.internal.IntegerConstant
private import semmle.code.cpp.ir.internal.IntegerPartial
private import IR
language[monotonicAggregates]
IntValue getConstantValue(Instruction instr) {
int getConstantValue(Instruction instr) {
result = instr.(IntegerConstantInstruction).getValue().toInt() or
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
exists(BinaryInstruction binInstr, int left, int right |
binInstr = instr and
left = getConstantValue(binInstr.getLeftOperand()) and
right = getConstantValue(binInstr.getRightOperand()) and
@@ -22,7 +22,7 @@ IntValue getConstantValue(Instruction instr) {
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
)
) or
exists(UnaryInstruction unaryInstr, IntValue src |
exists(UnaryInstruction unaryInstr, int src |
unaryInstr = instr and
src = getConstantValue(unaryInstr.getOperand()) and
(

View File

@@ -1,11 +1,11 @@
private import internal.ConstantAnalysisInternal
import semmle.code.cpp.ir.internal.IntegerConstant
private import semmle.code.cpp.ir.internal.IntegerPartial
private import IR
language[monotonicAggregates]
IntValue getConstantValue(Instruction instr) {
int getConstantValue(Instruction instr) {
result = instr.(IntegerConstantInstruction).getValue().toInt() or
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
exists(BinaryInstruction binInstr, int left, int right |
binInstr = instr and
left = getConstantValue(binInstr.getLeftOperand()) and
right = getConstantValue(binInstr.getRightOperand()) and
@@ -22,7 +22,7 @@ IntValue getConstantValue(Instruction instr) {
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
)
) or
exists(UnaryInstruction unaryInstr, IntValue src |
exists(UnaryInstruction unaryInstr, int src |
unaryInstr = instr and
src = getConstantValue(unaryInstr.getOperand()) and
(

View File

@@ -1,11 +1,10 @@
private import ReachableBlockInternal
private import semmle.code.cpp.ir.internal.IntegerConstant
private import IR
private import ConstantAnalysis
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
exists(int conditionValue |
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
if conditionValue = 0 then
kind instanceof TrueEdge
else

View File

@@ -1,11 +1,11 @@
private import internal.ConstantAnalysisInternal
import semmle.code.cpp.ir.internal.IntegerConstant
private import semmle.code.cpp.ir.internal.IntegerPartial
private import IR
language[monotonicAggregates]
IntValue getConstantValue(Instruction instr) {
int getConstantValue(Instruction instr) {
result = instr.(IntegerConstantInstruction).getValue().toInt() or
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
exists(BinaryInstruction binInstr, int left, int right |
binInstr = instr and
left = getConstantValue(binInstr.getLeftOperand()) and
right = getConstantValue(binInstr.getRightOperand()) and
@@ -22,7 +22,7 @@ IntValue getConstantValue(Instruction instr) {
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
)
) or
exists(UnaryInstruction unaryInstr, IntValue src |
exists(UnaryInstruction unaryInstr, int src |
unaryInstr = instr and
src = getConstantValue(unaryInstr.getOperand()) and
(

View File

@@ -1,11 +1,10 @@
private import ReachableBlockInternal
private import semmle.code.cpp.ir.internal.IntegerConstant
private import IR
private import ConstantAnalysis
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
exists(int conditionValue |
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
if conditionValue = 0 then
kind instanceof TrueEdge
else

View File

@@ -0,0 +1,134 @@
/**
* Provides basic arithmetic operations that have no result if their result
* would overflow a 32-bit two's complement integer.
*/
/**
* Gets the value of the maximum representable integer.
*/
int maxValue() {
result = 2147483647
}
/**
* Gets the value of the minimum representable integer.
*/
int minValue() {
result = -2147483648
}
/**
* Holds if the value `f` is within the range of representable integers.
*/
pragma[inline]
bindingset[f]
private predicate isRepresentable(float f) {
(f >= minValue()) and (f <= maxValue())
}
/**
* Returns `a + b`. If the addition overflows, there is no result.
*/
bindingset[a, b]
int add(int a, int b) {
isRepresentable((float)a + (float)b) and
result = a + b
}
/**
* Returns `a - b`. If the subtraction overflows, there is no result.
*/
bindingset[a, b]
int sub(int a, int b) {
isRepresentable((float)a - (float)b) and
result = a - b
}
/**
* Returns `a * b`. If the multiplication overflows, there is no result. If
* either input is not given, and the other input is non-zero, there is no
* result.
*/
bindingset[a, b]
int mul(int a, int b) {
a = 0 and
result = 0
or
b = 0 and
result = 0
or
isRepresentable((float)a * (float)b) and
result = a * b
}
/**
* Returns `a / b`. If the division overflows, there is no result.
*/
bindingset[a, b]
int div(int a, int b) {
b != 0 and (a != minValue() or b != -1) and
result = a / b
}
/** Returns `a == b`. */
bindingset[a, b]
int compareEQ(int a, int b) {
if a = b then
result = 1
else
result = 0
}
/** Returns `a != b`. */
bindingset[a, b]
int compareNE(int a, int b) {
if a != b then
result = 1
else
result = 0
}
/** Returns `a < b`. */
bindingset[a, b]
int compareLT(int a, int b) {
if a < b then
result = 1
else
result = 0
}
/** Returns `a > b`. */
bindingset[a, b]
int compareGT(int a, int b) {
if a > b then
result = 1
else
result = 0
}
/** Returns `a <= b`. */
bindingset[a, b]
int compareLE(int a, int b) {
if a <= b then
result = 1
else
result = 0
}
/** Returns `a >= b`. */
bindingset[a, b]
int compareGE(int a, int b) {
if a >= b then
result = 1
else
result = 0
}
/**
* Returns `-a`. If the negation would overflow, there is no result.
*/
bindingset[a]
int neg(int a) {
a != minValue() and
result = -a
}