Skip to content

Commit 050a563

Browse files
committed
C++: Infer a constant upper bound whenever we convert to a 'larger' upper bound (and similarly for lower bounds).
1 parent 33eaeb9 commit 050a563

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,8 @@ class SemConditionalExpr extends SemKnownExpr {
307307
branch = false and result = falseResult
308308
}
309309
}
310+
311+
/** Holds if `upper = true` and `e <= bound` or `upper = false` and `e >= bound`. */
312+
predicate semHasConstantBoundConstantSpecific(SemExpr e, float bound, boolean upper) {
313+
Specific::hasConstantBoundConstantSpecific(e, bound, upper)
314+
}

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,50 @@ module SemanticExprConfig {
434434

435435
/** Gets the expression associated with `instr`. */
436436
SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) }
437+
438+
private predicate typeBounds(SemType t, float lb, float ub) {
439+
exists(SemIntegerType integralType, float limit |
440+
integralType = t and limit = 2.pow(8 * integralType.getByteSize())
441+
|
442+
if integralType instanceof SemBooleanType
443+
then lb = 0 and ub = 1
444+
else
445+
if integralType.isSigned()
446+
then (
447+
lb = -(limit / 2) and ub = (limit / 2) - 1
448+
) else (
449+
lb = 0 and ub = limit - 1
450+
)
451+
)
452+
or
453+
// This covers all floating point types. The range is (-Inf, +Inf).
454+
t instanceof SemFloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
455+
}
456+
457+
/**
458+
* Holds if `upper = true` and `e <= bound` or `upper = false` and `e >= bound` based
459+
* only on type information.
460+
*/
461+
predicate hasConstantBoundConstantSpecific(Expr e, float bound, boolean upper) {
462+
exists(
463+
SemType converted, SemType unconverted, float unconvertedLb, float convertedLb,
464+
float unconvertedUb, float convertedUb
465+
|
466+
unconverted = getSemanticType(e.getUnconverted().getResultIRType()) and
467+
converted = getSemanticType(e.getConverted().getResultIRType()) and
468+
typeBounds(unconverted, unconvertedLb, unconvertedUb) and
469+
typeBounds(converted, convertedLb, convertedUb) and
470+
(
471+
upper = true and
472+
unconvertedUb < convertedUb and
473+
bound = unconvertedUb
474+
or
475+
upper = false and
476+
unconvertedLb > convertedLb and
477+
bound = unconvertedLb
478+
)
479+
)
480+
}
437481
}
438482

439483
predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1;
@@ -457,3 +501,5 @@ IRBound::Bound getCppBound(SemBound bound) { bound = result }
457501
SemGuard getSemanticGuard(IRGuards::IRGuardCondition guard) { result = guard }
458502

459503
IRGuards::IRGuardCondition getCppGuard(SemGuard guard) { guard = result }
504+
505+
predicate hasConstantBoundConstantSpecific = SemanticExprConfig::hasConstantBoundConstantSpecific/3;

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisConstantSpecific.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ module CppLangImplConstant implements LangSig<FloatDelta> {
7474
/**
7575
* Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`).
7676
*/
77-
predicate hasConstantBound(SemExpr e, float bound, boolean upper) { none() }
77+
predicate hasConstantBound(SemExpr e, float bound, boolean upper) {
78+
semHasConstantBoundConstantSpecific(e, bound, upper)
79+
}
7880

7981
/**
8082
* Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`).

0 commit comments

Comments
 (0)