Skip to content

Commit 16004fa

Browse files
authored
Merge pull request #197 from rdmarsh2/rdmarsh/cpp/ir-guards
IR-based guards library
2 parents 87271fb + 93732d8 commit 16004fa

File tree

15 files changed

+1860
-30
lines changed

15 files changed

+1860
-30
lines changed

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

Lines changed: 485 additions & 0 deletions
Large diffs are not rendered by default.

cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {}
7676

7777
abstract class CompareOpcode extends BinaryOpcode {}
7878

79+
abstract class RelationalOpcode extends CompareOpcode {}
80+
7981
abstract class CopyOpcode extends Opcode {}
8082

8183
abstract class MemoryAccessOpcode extends Opcode {}
@@ -117,10 +119,10 @@ module Opcode {
117119
class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } }
118120
class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } }
119121
class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } }
120-
class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
121-
class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
122-
class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
123-
class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
122+
class CompareLT extends RelationalOpcode, TCompareLT { override final string toString() { result = "CompareLT" } }
123+
class CompareGT extends RelationalOpcode, TCompareGT { override final string toString() { result = "CompareGT" } }
124+
class CompareLE extends RelationalOpcode, TCompareLE { override final string toString() { result = "CompareLE" } }
125+
class CompareGE extends RelationalOpcode, TCompareGE { override final string toString() { result = "CompareGE" } }
124126
class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } }
125127
class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } }
126128
class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } }

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
8989
dominates(result.getAPredecessor()) and
9090
not strictlyDominates(result)
9191
}
92+
93+
/**
94+
* Holds if this block is reachable from the entry point of its function
95+
*/
96+
final predicate isReachableFromFunctionEntry() {
97+
this = getFunctionIR().getEntryBlock() or
98+
getAPredecessor().isReachableFromFunctionEntry()
99+
}
92100
}

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

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,19 @@ class Instruction extends Construction::TInstruction {
310310
}
311311

312312
/**
313-
* Gets the `Expr` whose results is computed by this instruction, if any.
313+
* Gets the `Expr` whose result is computed by this instruction, if any.
314314
*/
315-
final Expr getResultExpression() {
316-
result = Construction::getInstructionResultExpression(this)
315+
final Expr getConvertedResultExpression() {
316+
result = Construction::getInstructionConvertedResultExpression(this)
317317
}
318+
319+
/**
320+
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
321+
*/
322+
final Expr getUnconvertedResultExpression() {
323+
result = Construction::getInstructionUnconvertedResultExpression(this)
324+
}
325+
318326

319327
/**
320328
* Gets the type of the result produced by this instruction. If the
@@ -967,28 +975,110 @@ class CompareNEInstruction extends CompareInstruction {
967975
}
968976
}
969977

970-
class CompareLTInstruction extends CompareInstruction {
978+
/**
979+
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
980+
*/
981+
class RelationalInstruction extends CompareInstruction {
982+
RelationalInstruction() {
983+
opcode instanceof RelationalOpcode
984+
}
985+
/**
986+
* Gets the operand on the "greater" (or "greater-or-equal") side
987+
* of this relational instruction, that is, the side that is larger
988+
* if the overall instruction evaluates to `true`; for example on
989+
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
990+
*/
991+
Instruction getGreaterOperand() {
992+
none()
993+
}
994+
995+
/**
996+
* Gets the operand on the "lesser" (or "lesser-or-equal") side
997+
* of this relational instruction, that is, the side that is smaller
998+
* if the overall instruction evaluates to `true`; for example on
999+
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
1000+
*/
1001+
Instruction getLesserOperand() {
1002+
none()
1003+
}
1004+
/**
1005+
* Holds if this relational instruction is strict (is not an "or-equal" instruction).
1006+
*/
1007+
predicate isStrict() {
1008+
none()
1009+
}
1010+
}
1011+
1012+
class CompareLTInstruction extends RelationalInstruction {
9711013
CompareLTInstruction() {
9721014
opcode instanceof Opcode::CompareLT
9731015
}
1016+
1017+
override Instruction getLesserOperand() {
1018+
result = getLeftOperand()
1019+
}
1020+
1021+
override Instruction getGreaterOperand() {
1022+
result = getRightOperand()
1023+
}
1024+
1025+
override predicate isStrict() {
1026+
any()
1027+
}
9741028
}
9751029

976-
class CompareGTInstruction extends CompareInstruction {
1030+
class CompareGTInstruction extends RelationalInstruction {
9771031
CompareGTInstruction() {
9781032
opcode instanceof Opcode::CompareGT
9791033
}
1034+
1035+
override Instruction getLesserOperand() {
1036+
result = getRightOperand()
1037+
}
1038+
1039+
override Instruction getGreaterOperand() {
1040+
result = getLeftOperand()
1041+
}
1042+
1043+
override predicate isStrict() {
1044+
any()
1045+
}
9801046
}
9811047

982-
class CompareLEInstruction extends CompareInstruction {
1048+
class CompareLEInstruction extends RelationalInstruction {
9831049
CompareLEInstruction() {
9841050
opcode instanceof Opcode::CompareLE
9851051
}
1052+
1053+
override Instruction getLesserOperand() {
1054+
result = getLeftOperand()
1055+
}
1056+
1057+
override Instruction getGreaterOperand() {
1058+
result = getRightOperand()
1059+
}
1060+
1061+
override predicate isStrict() {
1062+
none()
1063+
}
9861064
}
9871065

988-
class CompareGEInstruction extends CompareInstruction {
1066+
class CompareGEInstruction extends RelationalInstruction {
9891067
CompareGEInstruction() {
9901068
opcode instanceof Opcode::CompareGE
9911069
}
1070+
1071+
override Instruction getLesserOperand() {
1072+
result = getRightOperand()
1073+
}
1074+
1075+
override Instruction getGreaterOperand() {
1076+
result = getLeftOperand()
1077+
}
1078+
1079+
override predicate isStrict() {
1080+
none()
1081+
}
9921082
}
9931083

9941084
class SwitchInstruction extends Instruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,12 @@ cached private module Cached {
197197
)
198198
}
199199

200-
cached Expr getInstructionResultExpression(Instruction instruction) {
201-
result = getOldInstruction(instruction).getResultExpression()
200+
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
201+
result = getOldInstruction(instruction).getConvertedResultExpression()
202+
}
203+
204+
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
205+
result = getOldInstruction(instruction).getUnconvertedResultExpression()
202206
}
203207

204208
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
8989
dominates(result.getAPredecessor()) and
9090
not strictlyDominates(result)
9191
}
92+
93+
/**
94+
* Holds if this block is reachable from the entry point of its function
95+
*/
96+
final predicate isReachableFromFunctionEntry() {
97+
this = getFunctionIR().getEntryBlock() or
98+
getAPredecessor().isReachableFromFunctionEntry()
99+
}
92100
}

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

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,19 @@ class Instruction extends Construction::TInstruction {
310310
}
311311

312312
/**
313-
* Gets the `Expr` whose results is computed by this instruction, if any.
313+
* Gets the `Expr` whose result is computed by this instruction, if any.
314314
*/
315-
final Expr getResultExpression() {
316-
result = Construction::getInstructionResultExpression(this)
315+
final Expr getConvertedResultExpression() {
316+
result = Construction::getInstructionConvertedResultExpression(this)
317317
}
318+
319+
/**
320+
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
321+
*/
322+
final Expr getUnconvertedResultExpression() {
323+
result = Construction::getInstructionUnconvertedResultExpression(this)
324+
}
325+
318326

319327
/**
320328
* Gets the type of the result produced by this instruction. If the
@@ -967,28 +975,110 @@ class CompareNEInstruction extends CompareInstruction {
967975
}
968976
}
969977

970-
class CompareLTInstruction extends CompareInstruction {
978+
/**
979+
* Represents an instruction that does a relative comparison of two values, such as `<` or `>=`.
980+
*/
981+
class RelationalInstruction extends CompareInstruction {
982+
RelationalInstruction() {
983+
opcode instanceof RelationalOpcode
984+
}
985+
/**
986+
* Gets the operand on the "greater" (or "greater-or-equal") side
987+
* of this relational instruction, that is, the side that is larger
988+
* if the overall instruction evaluates to `true`; for example on
989+
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
990+
*/
991+
Instruction getGreaterOperand() {
992+
none()
993+
}
994+
995+
/**
996+
* Gets the operand on the "lesser" (or "lesser-or-equal") side
997+
* of this relational instruction, that is, the side that is smaller
998+
* if the overall instruction evaluates to `true`; for example on
999+
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
1000+
*/
1001+
Instruction getLesserOperand() {
1002+
none()
1003+
}
1004+
/**
1005+
* Holds if this relational instruction is strict (is not an "or-equal" instruction).
1006+
*/
1007+
predicate isStrict() {
1008+
none()
1009+
}
1010+
}
1011+
1012+
class CompareLTInstruction extends RelationalInstruction {
9711013
CompareLTInstruction() {
9721014
opcode instanceof Opcode::CompareLT
9731015
}
1016+
1017+
override Instruction getLesserOperand() {
1018+
result = getLeftOperand()
1019+
}
1020+
1021+
override Instruction getGreaterOperand() {
1022+
result = getRightOperand()
1023+
}
1024+
1025+
override predicate isStrict() {
1026+
any()
1027+
}
9741028
}
9751029

976-
class CompareGTInstruction extends CompareInstruction {
1030+
class CompareGTInstruction extends RelationalInstruction {
9771031
CompareGTInstruction() {
9781032
opcode instanceof Opcode::CompareGT
9791033
}
1034+
1035+
override Instruction getLesserOperand() {
1036+
result = getRightOperand()
1037+
}
1038+
1039+
override Instruction getGreaterOperand() {
1040+
result = getLeftOperand()
1041+
}
1042+
1043+
override predicate isStrict() {
1044+
any()
1045+
}
9801046
}
9811047

982-
class CompareLEInstruction extends CompareInstruction {
1048+
class CompareLEInstruction extends RelationalInstruction {
9831049
CompareLEInstruction() {
9841050
opcode instanceof Opcode::CompareLE
9851051
}
1052+
1053+
override Instruction getLesserOperand() {
1054+
result = getLeftOperand()
1055+
}
1056+
1057+
override Instruction getGreaterOperand() {
1058+
result = getRightOperand()
1059+
}
1060+
1061+
override predicate isStrict() {
1062+
none()
1063+
}
9861064
}
9871065

988-
class CompareGEInstruction extends CompareInstruction {
1066+
class CompareGEInstruction extends RelationalInstruction {
9891067
CompareGEInstruction() {
9901068
opcode instanceof Opcode::CompareGE
9911069
}
1070+
1071+
override Instruction getLesserOperand() {
1072+
result = getRightOperand()
1073+
}
1074+
1075+
override Instruction getGreaterOperand() {
1076+
result = getLeftOperand()
1077+
}
1078+
1079+
override predicate isStrict() {
1080+
none()
1081+
}
9921082
}
9931083

9941084
class SwitchInstruction extends Instruction {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,25 @@ cached private module Cached {
7474
none()
7575
}
7676

77-
cached Expr getInstructionResultExpression(Instruction instruction) {
77+
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
7878
exists(TranslatedExpr translatedExpr |
7979
translatedExpr = getTranslatedExpr(result) and
8080
instruction = translatedExpr.getResult()
8181
)
8282
}
8383

84+
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
85+
exists(Expr converted, TranslatedExpr translatedExpr |
86+
result = converted.(Conversion).getExpr+()
87+
or
88+
result = converted
89+
|
90+
not result instanceof Conversion and
91+
translatedExpr = getTranslatedExpr(converted) and
92+
instruction = translatedExpr.getResult()
93+
)
94+
}
95+
8496
cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) {
8597
result = getInstructionTranslatedElement(instruction).getInstructionOperand(
8698
instruction.getTag(), tag)

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,12 @@ class IRBlock extends TIRBlock {
8989
dominates(result.getAPredecessor()) and
9090
not strictlyDominates(result)
9191
}
92+
93+
/**
94+
* Holds if this block is reachable from the entry point of its function
95+
*/
96+
final predicate isReachableFromFunctionEntry() {
97+
this = getFunctionIR().getEntryBlock() or
98+
getAPredecessor().isReachableFromFunctionEntry()
99+
}
92100
}

0 commit comments

Comments
 (0)