Skip to content

Commit 4170d4f

Browse files
C++: Handle relational operators in constant analysis
1 parent 5ba51e3 commit 4170d4f

File tree

13 files changed

+445
-227
lines changed

13 files changed

+445
-227
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ IntValue getConstantValue(Instruction instr) {
1313
binInstr instanceof AddInstruction and result = add(left, right) or
1414
binInstr instanceof SubInstruction and result = sub(left, right) or
1515
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right)
16+
binInstr instanceof DivInstruction and result = div(left, right) or
17+
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18+
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19+
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20+
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21+
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22+
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
1723
)
1824
) or
1925
exists(UnaryInstruction unaryInstr, IntValue src |

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ IntValue getConstantValue(Instruction instr) {
1313
binInstr instanceof AddInstruction and result = add(left, right) or
1414
binInstr instanceof SubInstruction and result = sub(left, right) or
1515
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right)
16+
binInstr instanceof DivInstruction and result = div(left, right) or
17+
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18+
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19+
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20+
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21+
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22+
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
1723
)
1824
) or
1925
exists(UnaryInstruction unaryInstr, IntValue src |

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ IntValue getConstantValue(Instruction instr) {
1313
binInstr instanceof AddInstruction and result = add(left, right) or
1414
binInstr instanceof SubInstruction and result = sub(left, right) or
1515
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right)
16+
binInstr instanceof DivInstruction and result = div(left, right) or
17+
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18+
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19+
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20+
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21+
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22+
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
1723
)
1824
) or
1925
exists(UnaryInstruction unaryInstr, IntValue src |

cpp/ql/src/semmle/code/cpp/ir/internal/IntegerConstant.qll

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,96 @@ IntValue div(IntValue a, IntValue b) {
102102
result = unknown()
103103
}
104104

105+
/**
106+
* Returns `a == b`. If either input is unknown, the result is unknown.
107+
*/
108+
bindingset[a, b]
109+
IntValue compareEQ(IntValue a, IntValue b) {
110+
if hasValue(a) and hasValue(b) then (
111+
if a = b then
112+
result = 1
113+
else
114+
result = 0
115+
)
116+
else
117+
result = unknown()
118+
}
119+
120+
/**
121+
* Returns `a != b`. If either input is unknown, the result is unknown.
122+
*/
123+
bindingset[a, b]
124+
IntValue compareNE(IntValue a, IntValue b) {
125+
if hasValue(a) and hasValue(b) then (
126+
if a != b then
127+
result = 1
128+
else
129+
result = 0
130+
)
131+
else
132+
result = unknown()
133+
}
134+
135+
/**
136+
* Returns `a < b`. If either input is unknown, the result is unknown.
137+
*/
138+
bindingset[a, b]
139+
IntValue compareLT(IntValue a, IntValue b) {
140+
if hasValue(a) and hasValue(b) then (
141+
if a < b then
142+
result = 1
143+
else
144+
result = 0
145+
)
146+
else
147+
result = unknown()
148+
}
149+
150+
/**
151+
* Returns `a > b`. If either input is unknown, the result is unknown.
152+
*/
153+
bindingset[a, b]
154+
IntValue compareGT(IntValue a, IntValue b) {
155+
if hasValue(a) and hasValue(b) then (
156+
if a > b then
157+
result = 1
158+
else
159+
result = 0
160+
)
161+
else
162+
result = unknown()
163+
}
164+
165+
/**
166+
* Returns `a <= b`. If either input is unknown, the result is unknown.
167+
*/
168+
bindingset[a, b]
169+
IntValue compareLE(IntValue a, IntValue b) {
170+
if hasValue(a) and hasValue(b) then (
171+
if a <= b then
172+
result = 1
173+
else
174+
result = 0
175+
)
176+
else
177+
result = unknown()
178+
}
179+
180+
/**
181+
* Returns `a >= b`. If either input is unknown, the result is unknown.
182+
*/
183+
bindingset[a, b]
184+
IntValue compareGE(IntValue a, IntValue b) {
185+
if hasValue(a) and hasValue(b) then (
186+
if a >= b then
187+
result = 1
188+
else
189+
result = 0
190+
)
191+
else
192+
result = unknown()
193+
}
194+
105195
/**
106196
* Return `-a`. If `a` is unknown, the result is unknown.
107197
*/

cpp/ql/test/library-tests/ir/constant_func/constant_func.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,18 @@ int UnreachableViaGoto() {
3939
}
4040

4141
int UnreachableIf(bool b) {
42+
int x = 5;
43+
int y = 10;
4244
if (b) {
43-
if (false) {
45+
if (x == y) {
4446
return 1;
4547
}
4648
else {
4749
return 0;
4850
}
4951
}
5052
else {
51-
if (true) {
53+
if (x < y) {
5254
return 0;
5355
}
5456
else {

cpp/ql/test/library-tests/ir/constants/constants.expected

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,49 @@
2121
| -1 * -INT_MAX | 2147483647 |
2222
| -1 - -INT_MAX | 2147483646 |
2323
| -1 - INT_MAX | unknown |
24+
| -3 != 6 | 1 |
25+
| -3 != -3 | 0 |
26+
| -3 != unknown | unknown |
27+
| -3 < 6 | 1 |
28+
| -3 < -3 | 0 |
29+
| -3 < -7 | 0 |
30+
| -3 < unknown | unknown |
31+
| -3 <= 6 | 1 |
32+
| -3 <= -3 | 1 |
33+
| -3 <= -7 | 0 |
34+
| -3 <= unknown | unknown |
35+
| -3 == 6 | 0 |
36+
| -3 == -3 | 1 |
37+
| -3 == unknown | unknown |
38+
| -3 > 6 | 0 |
39+
| -3 > -3 | 0 |
40+
| -3 > -7 | 1 |
41+
| -3 > unknown | unknown |
42+
| -3 >= 6 | 0 |
43+
| -3 >= -3 | 1 |
44+
| -3 >= -7 | 1 |
45+
| -3 >= unknown | unknown |
2446
| -35 / 7 | -5 |
2547
| -35 / 8 | -4 |
2648
| -35 / -7 | 5 |
2749
| -35 / -8 | 4 |
2850
| INT_MAX * INT_MAX | unknown |
2951
| INT_MAX / 0 | unknown |
52+
| unknown != 6 | unknown |
53+
| unknown != unknown | unknown |
3054
| unknown + 5 | unknown |
3155
| unknown + unknown | unknown |
3256
| unknown - 5 | unknown |
3357
| unknown - unknown | unknown |
3458
| unknown / 3 | unknown |
3559
| unknown / unknown | unknown |
60+
| unknown < 6 | unknown |
61+
| unknown < unknown | unknown |
62+
| unknown <= 6 | unknown |
63+
| unknown <= unknown | unknown |
64+
| unknown == 6 | unknown |
65+
| unknown == unknown | unknown |
66+
| unknown > 6 | unknown |
67+
| unknown > unknown | unknown |
68+
| unknown >= 6 | unknown |
69+
| unknown >= unknown | unknown |

cpp/ql/test/library-tests/ir/constants/constants.ql

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,39 @@ where
4545
expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or
4646
expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or
4747
expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or
48-
expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown())
48+
expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) or
49+
expr = "-3 == -3" and res = Ints::compareEQ(-3, -3) or
50+
expr = "-3 == 6" and res = Ints::compareEQ(-3, 6) or
51+
expr = "-3 == unknown" and res = Ints::compareEQ(-3, Ints::unknown()) or
52+
expr = "unknown == 6" and res = Ints::compareEQ(Ints::unknown(), 6) or
53+
expr = "unknown == unknown" and res = Ints::compareEQ(Ints::unknown(), Ints::unknown()) or
54+
expr = "-3 != -3" and res = Ints::compareNE(-3, -3) or
55+
expr = "-3 != 6" and res = Ints::compareNE(-3, 6) or
56+
expr = "-3 != unknown" and res = Ints::compareNE(-3, Ints::unknown()) or
57+
expr = "unknown != 6" and res = Ints::compareNE(Ints::unknown(), 6) or
58+
expr = "unknown != unknown" and res = Ints::compareNE(Ints::unknown(), Ints::unknown()) or
59+
expr = "-3 < -3" and res = Ints::compareLT(-3, -3) or
60+
expr = "-3 < 6" and res = Ints::compareLT(-3, 6) or
61+
expr = "-3 < -7" and res = Ints::compareLT(-3, -7) or
62+
expr = "-3 < unknown" and res = Ints::compareLT(-3, Ints::unknown()) or
63+
expr = "unknown < 6" and res = Ints::compareLT(Ints::unknown(), 6) or
64+
expr = "unknown < unknown" and res = Ints::compareLT(Ints::unknown(), Ints::unknown()) or
65+
expr = "-3 > -3" and res = Ints::compareGT(-3, -3) or
66+
expr = "-3 > 6" and res = Ints::compareGT(-3, 6) or
67+
expr = "-3 > -7" and res = Ints::compareGT(-3, -7) or
68+
expr = "-3 > unknown" and res = Ints::compareGT(-3, Ints::unknown()) or
69+
expr = "unknown > 6" and res = Ints::compareGT(Ints::unknown(), 6) or
70+
expr = "unknown > unknown" and res = Ints::compareGT(Ints::unknown(), Ints::unknown()) or
71+
expr = "-3 <= -3" and res = Ints::compareLE(-3, -3) or
72+
expr = "-3 <= 6" and res = Ints::compareLE(-3, 6) or
73+
expr = "-3 <= -7" and res = Ints::compareLE(-3, -7) or
74+
expr = "-3 <= unknown" and res = Ints::compareLE(-3, Ints::unknown()) or
75+
expr = "unknown <= 6" and res = Ints::compareLE(Ints::unknown(), 6) or
76+
expr = "unknown <= unknown" and res = Ints::compareLE(Ints::unknown(), Ints::unknown()) or
77+
expr = "-3 >= -3" and res = Ints::compareGE(-3, -3) or
78+
expr = "-3 >= 6" and res = Ints::compareGE(-3, 6) or
79+
expr = "-3 >= -7" and res = Ints::compareGE(-3, -7) or
80+
expr = "-3 >= unknown" and res = Ints::compareGE(-3, Ints::unknown()) or
81+
expr = "unknown >= 6" and res = Ints::compareGE(Ints::unknown(), 6) or
82+
expr = "unknown >= unknown" and res = Ints::compareGE(Ints::unknown(), Ints::unknown())
4983
select expr, resultString(res)

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6688,43 +6688,69 @@ ir.cpp:
66886688
# 1028| 0: b
66896689
# 1028| Type = bool
66906690
# 1028| body: { ... }
6691-
# 1029| 0: if (...) ...
6692-
# 1029| 0: b
6693-
# 1029| Type = bool
6694-
# 1029| ValueCategory = prvalue(load)
6695-
# 1029| 1: { ... }
6696-
# 1030| 0: if (...) ...
6697-
# 1030| 0: 0
6698-
# 1030| Type = bool
6699-
# 1030| Value = 0
6691+
# 1029| 0: declaration
6692+
# 1029| 0: definition of x
6693+
# 1029| Type = int
6694+
# 1029| init: initializer for x
6695+
# 1029| expr: 5
6696+
# 1029| Type = int
6697+
# 1029| Value = 5
6698+
# 1029| ValueCategory = prvalue
6699+
# 1030| 1: declaration
6700+
# 1030| 0: definition of y
6701+
# 1030| Type = int
6702+
# 1030| init: initializer for y
6703+
# 1030| expr: 10
6704+
# 1030| Type = int
6705+
# 1030| Value = 10
67006706
# 1030| ValueCategory = prvalue
6701-
# 1030| 1: { ... }
6702-
# 1031| 0: return ...
6703-
# 1031| 0: 1
6704-
# 1031| Type = int
6705-
# 1031| Value = 1
6706-
# 1031| ValueCategory = prvalue
6707-
# 1033| 2: { ... }
6708-
# 1034| 0: return ...
6709-
# 1034| 0: 0
6710-
# 1034| Type = int
6711-
# 1034| Value = 0
6712-
# 1034| ValueCategory = prvalue
6713-
# 1037| 2: { ... }
6714-
# 1038| 0: if (...) ...
6715-
# 1038| 0: 1
6716-
# 1038| Type = bool
6717-
# 1038| Value = 1
6718-
# 1038| ValueCategory = prvalue
6719-
# 1038| 1: { ... }
6720-
# 1039| 0: return ...
6721-
# 1039| 0: 0
6722-
# 1039| Type = int
6723-
# 1039| Value = 0
6724-
# 1039| ValueCategory = prvalue
6725-
# 1041| 2: { ... }
6726-
# 1042| 0: return ...
6727-
# 1042| 0: 1
6728-
# 1042| Type = int
6729-
# 1042| Value = 1
6730-
# 1042| ValueCategory = prvalue
6707+
# 1031| 2: if (...) ...
6708+
# 1031| 0: b
6709+
# 1031| Type = bool
6710+
# 1031| ValueCategory = prvalue(load)
6711+
# 1031| 1: { ... }
6712+
# 1032| 0: if (...) ...
6713+
# 1032| 0: ... == ...
6714+
# 1032| Type = bool
6715+
# 1032| ValueCategory = prvalue
6716+
# 1032| 0: x
6717+
# 1032| Type = int
6718+
# 1032| ValueCategory = prvalue(load)
6719+
# 1032| 1: y
6720+
# 1032| Type = int
6721+
# 1032| ValueCategory = prvalue(load)
6722+
# 1032| 1: { ... }
6723+
# 1033| 0: return ...
6724+
# 1033| 0: 1
6725+
# 1033| Type = int
6726+
# 1033| Value = 1
6727+
# 1033| ValueCategory = prvalue
6728+
# 1035| 2: { ... }
6729+
# 1036| 0: return ...
6730+
# 1036| 0: 0
6731+
# 1036| Type = int
6732+
# 1036| Value = 0
6733+
# 1036| ValueCategory = prvalue
6734+
# 1039| 2: { ... }
6735+
# 1040| 0: if (...) ...
6736+
# 1040| 0: ... < ...
6737+
# 1040| Type = bool
6738+
# 1040| ValueCategory = prvalue
6739+
# 1040| 0: x
6740+
# 1040| Type = int
6741+
# 1040| ValueCategory = prvalue(load)
6742+
# 1040| 1: y
6743+
# 1040| Type = int
6744+
# 1040| ValueCategory = prvalue(load)
6745+
# 1040| 1: { ... }
6746+
# 1041| 0: return ...
6747+
# 1041| 0: 0
6748+
# 1041| Type = int
6749+
# 1041| Value = 0
6750+
# 1041| ValueCategory = prvalue
6751+
# 1043| 2: { ... }
6752+
# 1044| 0: return ...
6753+
# 1044| 0: 1
6754+
# 1044| Type = int
6755+
# 1044| Value = 1
6756+
# 1044| ValueCategory = prvalue

0 commit comments

Comments
 (0)