Skip to content

Commit b86aeb6

Browse files
authored
Merge pull request #16364 from MathiasVP/ir-guards-with-boolean
C++: Support `IRGuard`s with no implicit boolean conversion
2 parents c04e596 + c32c810 commit b86aeb6

File tree

7 files changed

+160
-0
lines changed

7 files changed

+160
-0
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,27 @@ private predicate simple_comparison_eq(Instruction test, Operand op, int k, Abst
790790
exists(switch.getSuccessor(case)) and
791791
case.getValue().toInt() = k
792792
)
793+
or
794+
// There's no implicit CompareInstruction in files compiled as C since C
795+
// doesn't have implicit boolean conversions. So instead we check whether
796+
// there's a branch on a value of pointer or integer type.
797+
exists(ConditionalBranchInstruction branch, IRType type |
798+
not test instanceof CompareInstruction and
799+
type = test.getResultIRType() and
800+
(type instanceof IRAddressType or type instanceof IRIntegerType) and
801+
test = branch.getCondition() and
802+
op.getDef() = test
803+
|
804+
// We'd like to also include a case such as:
805+
// ```
806+
// k = 1 and
807+
// value.(BooleanValue).getValue() = true
808+
// ```
809+
// but all we know is that the value is non-zero in the true branch.
810+
// So we can only conclude something in the false branch.
811+
k = 0 and
812+
value.(BooleanValue).getValue() = false
813+
)
793814
}
794815

795816
private predicate complex_eq(

cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,24 @@ astGuardsCompare
148148
| 109 | y < 0+0 when ... < ... is true |
149149
| 109 | y >= 0+0 when ... < ... is false |
150150
| 109 | y >= 0+0 when ... \|\| ... is false |
151+
| 126 | 1 != 0 when 1 is true |
152+
| 126 | 1 != 0 when ... && ... is true |
153+
| 126 | 1 == 0 when 1 is false |
154+
| 126 | call to test3_condition != 0 when ... && ... is true |
155+
| 126 | call to test3_condition != 0 when call to test3_condition is true |
156+
| 126 | call to test3_condition == 0 when call to test3_condition is false |
157+
| 131 | b != 0 when b is true |
158+
| 131 | b == 0 when b is false |
159+
| 137 | 0 != 0 when 0 is true |
160+
| 137 | 0 == 0 when 0 is false |
161+
| 146 | ! ... != 0 when ! ... is true |
162+
| 146 | ! ... == 0 when ! ... is false |
163+
| 152 | x != 0 when ... && ... is true |
164+
| 152 | x != 0 when x is true |
165+
| 152 | x == 0 when x is false |
166+
| 152 | y != 0 when ... && ... is true |
167+
| 152 | y != 0 when y is true |
168+
| 152 | y == 0 when y is false |
151169
| 156 | ... + ... != x+0 when ... == ... is false |
152170
| 156 | ... + ... == x+0 when ... == ... is true |
153171
| 156 | x != ... + ...+0 when ... == ... is false |
@@ -186,6 +204,8 @@ astGuardsCompare
186204
| 175 | call to foo != 0+0 when ... == ... is false |
187205
| 175 | call to foo == 0 when ... == ... is true |
188206
| 175 | call to foo == 0+0 when ... == ... is true |
207+
| 181 | x != 0 when x is true |
208+
| 181 | x == 0 when x is false |
189209
astGuardsControl
190210
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
191211
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
@@ -487,8 +507,27 @@ astGuardsEnsure_const
487507
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 109 | 109 |
488508
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
489509
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
510+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
511+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
512+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
513+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
514+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
515+
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
516+
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
517+
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
518+
| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
519+
| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
520+
| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
521+
| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
522+
| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 152 | 152 |
523+
| test.c:152:10:152:15 | ... && ... | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
524+
| test.c:152:10:152:15 | ... && ... | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
525+
| test.c:152:15:152:15 | y | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
490526
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | != | 0 | 175 | 175 |
491527
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | == | 0 | 175 | 175 |
528+
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 181 | 182 |
529+
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 186 | 180 |
530+
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | == | 0 | 183 | 184 |
492531
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
493532
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
494533
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
@@ -640,6 +679,20 @@ irGuardsCompare
640679
| 109 | y < 0+0 when CompareLT: ... < ... is true |
641680
| 109 | y >= 0 when CompareLT: ... < ... is false |
642681
| 109 | y >= 0+0 when CompareLT: ... < ... is false |
682+
| 126 | 1 != 0 when Constant: 1 is true |
683+
| 126 | 1 == 0 when Constant: 1 is false |
684+
| 126 | call to test3_condition != 0 when Call: call to test3_condition is true |
685+
| 126 | call to test3_condition == 0 when Call: call to test3_condition is false |
686+
| 131 | b != 0 when Load: b is true |
687+
| 131 | b == 0 when Load: b is false |
688+
| 137 | 0 != 0 when Constant: 0 is true |
689+
| 137 | 0 == 0 when Constant: 0 is false |
690+
| 146 | ! ... != 0 when LogicalNot: ! ... is true |
691+
| 146 | ! ... == 0 when LogicalNot: ! ... is false |
692+
| 152 | x != 0 when Load: x is true |
693+
| 152 | x == 0 when Load: x is false |
694+
| 152 | y != 0 when Load: y is true |
695+
| 152 | y == 0 when Load: y is false |
643696
| 156 | ... + ... != x+0 when CompareEQ: ... == ... is false |
644697
| 156 | ... + ... == x+0 when CompareEQ: ... == ... is true |
645698
| 156 | x != ... + ...+0 when CompareEQ: ... == ... is false |
@@ -678,6 +731,8 @@ irGuardsCompare
678731
| 175 | call to foo != 0+0 when CompareEQ: ... == ... is false |
679732
| 175 | call to foo == 0 when CompareEQ: ... == ... is true |
680733
| 175 | call to foo == 0+0 when CompareEQ: ... == ... is true |
734+
| 181 | x != 0 when Load: x is true |
735+
| 181 | x == 0 when Load: x is false |
681736
irGuardsControl
682737
| test.c:7:9:7:13 | CompareGT: ... > ... | false | 11 | 11 |
683738
| test.c:7:9:7:13 | CompareGT: ... > ... | true | 8 | 8 |
@@ -999,8 +1054,21 @@ irGuardsEnsure_const
9991054
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 109 | 109 |
10001055
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 113 | 113 |
10011056
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | 0 | 113 | 113 |
1057+
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 126 | 126 |
1058+
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 127 | 127 |
1059+
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 131 | 131 |
1060+
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 132 | 132 |
1061+
| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 134 | 134 |
1062+
| test.c:126:12:126:26 | Call: call to test3_condition | test.c:126:12:126:26 | Call: call to test3_condition | != | 0 | 127 | 127 |
1063+
| test.c:131:7:131:7 | Load: b | test.c:131:7:131:7 | Load: b | != | 0 | 132 | 132 |
1064+
| test.c:137:7:137:7 | Constant: 0 | test.c:137:7:137:7 | Constant: 0 | == | 0 | 142 | 142 |
1065+
| test.c:146:7:146:8 | LogicalNot: ! ... | test.c:146:7:146:8 | LogicalNot: ! ... | != | 0 | 147 | 147 |
1066+
| test.c:152:10:152:10 | Load: x | test.c:152:10:152:10 | Load: x | != | 0 | 152 | 152 |
1067+
| test.c:152:15:152:15 | Load: y | test.c:152:15:152:15 | Load: y | != | 0 | 152 | 152 |
10021068
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | != | 0 | 175 | 175 |
10031069
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | == | 0 | 175 | 175 |
1070+
| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | != | 0 | 182 | 182 |
1071+
| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | == | 0 | 184 | 184 |
10041072
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | 0 | 19 | 19 |
10051073
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 |
10061074
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 |

cpp/ql/test/library-tests/controlflow/guards/Guards.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
| test.c:137:7:137:7 | 0 |
2727
| test.c:146:7:146:8 | ! ... |
2828
| test.c:146:8:146:8 | x |
29+
| test.c:152:8:152:8 | p |
30+
| test.c:158:8:158:9 | ! ... |
31+
| test.c:158:9:158:9 | p |
32+
| test.c:164:8:164:8 | s |
33+
| test.c:170:8:170:9 | ! ... |
34+
| test.c:170:9:170:9 | s |
2935
| test.cpp:18:8:18:10 | call to get |
3036
| test.cpp:31:7:31:13 | ... == ... |
3137
| test.cpp:42:13:42:20 | call to getABool |

cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,23 @@
149149
| 111 | 0.0 == i+0 when ... != ... is false |
150150
| 111 | i != 0.0+0 when ... != ... is true |
151151
| 111 | i == 0.0+0 when ... != ... is false |
152+
| 126 | 1 != 0 when 1 is true |
153+
| 126 | 1 != 0 when ... && ... is true |
154+
| 126 | 1 == 0 when 1 is false |
155+
| 126 | call to test3_condition != 0 when ... && ... is true |
156+
| 126 | call to test3_condition != 0 when call to test3_condition is true |
157+
| 126 | call to test3_condition == 0 when call to test3_condition is false |
158+
| 131 | b != 0 when b is true |
159+
| 131 | b == 0 when b is false |
160+
| 137 | 0 != 0 when 0 is true |
161+
| 137 | 0 == 0 when 0 is false |
162+
| 146 | ! ... != 0 when ! ... is true |
163+
| 146 | ! ... == 0 when ! ... is false |
164+
| 152 | p != 0 when p is true |
165+
| 152 | p == 0 when p is false |
166+
| 158 | ! ... != 0 when ! ... is true |
167+
| 158 | ! ... == 0 when ! ... is false |
168+
| 164 | s != 0 when s is true |
169+
| 164 | s == 0 when s is false |
170+
| 170 | ! ... != 0 when ! ... is true |
171+
| 170 | ! ... == 0 when ! ... is false |

cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@
7979
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
8080
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
8181
| test.c:146:8:146:8 | x | false | 146 | 147 |
82+
| test.c:152:8:152:8 | p | true | 152 | 154 |
83+
| test.c:158:8:158:9 | ! ... | true | 158 | 160 |
84+
| test.c:158:9:158:9 | p | false | 158 | 160 |
85+
| test.c:164:8:164:8 | s | true | 164 | 166 |
86+
| test.c:170:8:170:9 | ! ... | true | 170 | 172 |
87+
| test.c:170:9:170:9 | s | false | 170 | 172 |
8288
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
8389
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
8490
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |

cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,21 @@ unary
234234
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
235235
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
236236
| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
237+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
238+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
239+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
240+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
241+
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
242+
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
243+
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
244+
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
245+
| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
246+
| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
247+
| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
248+
| test.c:152:8:152:8 | p | test.c:152:8:152:8 | p | != | 0 | 152 | 154 |
249+
| test.c:158:8:158:9 | ! ... | test.c:158:8:158:9 | ! ... | != | 0 | 158 | 160 |
250+
| test.c:164:8:164:8 | s | test.c:164:8:164:8 | s | != | 0 | 164 | 166 |
251+
| test.c:170:8:170:9 | ! ... | test.c:170:8:170:9 | ! ... | != | 0 | 170 | 172 |
237252
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
238253
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
239254
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |

cpp/ql/test/library-tests/controlflow/guards/test.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,27 @@ void test5(int x) {
147147
test3();
148148
}
149149
}
150+
151+
void test6(char* p) {
152+
if(p) {
153+
154+
}
155+
}
156+
157+
void test7(char* p) {
158+
if(!p) {
159+
160+
}
161+
}
162+
163+
void test8(short s) {
164+
if(s) {
165+
166+
}
167+
}
168+
169+
void test9(short s) {
170+
if(!s) {
171+
172+
}
173+
}

0 commit comments

Comments
 (0)