mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
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:
@@ -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
|
||||
(
|
||||
|
||||
@@ -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
|
||||
(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
(
|
||||
|
||||
@@ -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
|
||||
|
||||
134
cpp/ql/src/semmle/code/cpp/ir/internal/IntegerPartial.qll
Normal file
134
cpp/ql/src/semmle/code/cpp/ir/internal/IntegerPartial.qll
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user