Skip to content

Commit 64f23eb

Browse files
authored
Merge pull request github#12436 from MathiasVP/ir-range-analysis-for-unary-minus
C++: IR-based range analysis for unary minus
2 parents 0c95ab2 + 619266d commit 64f23eb

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,15 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
936936
bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
937937
}
938938

939+
/**
940+
* Computes a normal form of `x` where -0.0 has changed to +0.0. This can be
941+
* needed on the lesser side of a floating-point comparison or on both sides of
942+
* a floating point equality because QL does not follow IEEE in floating-point
943+
* comparisons but instead defines -0.0 to be less than and distinct from 0.0.
944+
*/
945+
bindingset[x]
946+
private float normalizeFloatUp(float x) { result = x + 0.0 }
947+
939948
/**
940949
* Holds if `b + delta` is a valid bound for `e`.
941950
* - `upper = true` : `e <= b + delta`
@@ -1020,6 +1029,15 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10201029
or
10211030
upper = false and delta = D::fromFloat(D::toFloat(d1).minimum(D::toFloat(d2)))
10221031
)
1032+
or
1033+
exists(SemExpr mid, D::Delta d, float f |
1034+
e.(SemNegateExpr).getOperand() = mid and
1035+
b instanceof SemZeroBound and
1036+
bounded(mid, b, d, upper.booleanNot(), fromBackEdge, origdelta, reason) and
1037+
f = normalizeFloatUp(-D::toFloat(d)) and
1038+
delta = D::fromFloat(f) and
1039+
if semPositive(e) then f >= 0 else any()
1040+
)
10231041
)
10241042
}
10251043

cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ int test_unary(int a) {
231231
int b = +a;
232232
range(b); // $ range=<=11 range=>=3
233233
int c = -a;
234-
range(c);
235-
range(b+c); // $ range=<=10 range="<=+ ...:a-1" range=">=- ...+1"
234+
range(c); // $ range=<=-3 range=>=-11
235+
range(b+c); // $ range=<=10 range="<=+ ...:a-1" range=">=- ...+1" range=>=-10
236236
total += b+c;
237237
range(total);
238238
}
@@ -241,8 +241,8 @@ int test_unary(int a) {
241241
int b = +a;
242242
range(b); // $ range=<=11 range=>=0
243243
int c = -a;
244-
range(c);
245-
range(b+c); // $ range=<=11 range="<=+ ...:a+0" range=">=- ...+0"
244+
range(c); // $ range=<=0 range=>=-11
245+
range(b+c); // $ range=<=11 range="<=+ ...:a+0" range=">=- ...+0" range=>=-11
246246
total += b+c;
247247
range(total);
248248
}
@@ -251,7 +251,7 @@ int test_unary(int a) {
251251
int b = +a;
252252
range(b); // $ range=<=11 range=>=-7
253253
int c = -a;
254-
range(c);
254+
range(c); // $ range=<=7 range=>=-11
255255
range(b+c);
256256
total += b+c;
257257
range(total);
@@ -261,7 +261,7 @@ int test_unary(int a) {
261261
int b = +a;
262262
range(b); // $ range=<=1 range=>=-7
263263
int c = -a;
264-
range(c);
264+
range(c); // $ range=<=7 range=>=-1
265265
range(b+c);
266266
total += b+c;
267267
range(total);
@@ -271,8 +271,8 @@ int test_unary(int a) {
271271
int b = +a;
272272
range(b); // $ range=<=0 range=>=-7
273273
int c = -a;
274-
range(c);
275-
range(b+c); // $ range="<=- ...+0" range=">=+ ...:a+0" range=>=-7
274+
range(c); // $ range=<=7 range=>=0
275+
range(b+c); // $ range="<=- ...+0" range=">=+ ...:a+0" range=>=-7 range=<=7
276276
total += b+c;
277277
range(total);
278278
}
@@ -281,8 +281,8 @@ int test_unary(int a) {
281281
int b = +a;
282282
range(b); // $ range=<=-2 range=>=-7
283283
int c = -a;
284-
range(c);
285-
range(b+c); // $ range="<=- ...-1" range=">=+ ...:a+1" range=>=-6
284+
range(c); // $ range=<=7 range=>=2
285+
range(b+c); // $ range="<=- ...-1" range=">=+ ...:a+1" range=>=-6 range=<=6
286286
total += b+c;
287287
range(total);
288288
}
@@ -552,7 +552,7 @@ int test16(int x) {
552552
range(x); // $ range=<=-1 range=>=0
553553
return 1;
554554
}
555-
range(d); // $ range===3
555+
range(d); // $ range=<=0 range=>=3 // Unreachable code
556556
range(x); // $ range=<=-1 range=>=0
557557
}
558558
range(x); // $ range=>=0
@@ -997,3 +997,15 @@ void test_overflow() {
997997
range(x + y); // $ range===-2147483393
998998
}
999999
}
1000+
1001+
void test_negate_unsigned(unsigned u) {
1002+
if(10 < u && u < 20) {
1003+
range<unsigned>(-u); // underflows
1004+
}
1005+
}
1006+
1007+
void test_negate_signed(int s) {
1008+
if(10 < s && s < 20) {
1009+
range<int>(-s); // $ range=<=-11 range=>=-19
1010+
}
1011+
}

0 commit comments

Comments
 (0)