diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 4a8f39d79f2..fe89d8ebbe5 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -91,13 +91,30 @@ private float wideningUpperBounds(ArithmeticType t) { result = 1.0 / 0.0 // +Inf } +/** + * Gets the value of the expression `e`, if it is a constant. + * This predicate also handles the case of constant variables initialized in compilation units, + * which doesn't necessarily have a getValue() result from the extractor. + */ +private string getValue(Expr e) { + if exists(e.getValue()) + then result = e.getValue() + else + exists(VariableAccess access, Variable v | + e = access and + v = access.getTarget() and + v.getUnderlyingType().isConst() and + result = getValue(v.getAnAssignedValue()) + ) +} + /** Set of expressions which we know how to analyze. */ private predicate analyzableExpr(Expr e) { // The type of the expression must be arithmetic. We reuse the logic in // `exprMinVal` to check this. exists(exprMinVal(e)) and ( - exists(e.getValue().toFloat()) or + exists(getValue(e).toFloat()) or e instanceof UnaryPlusExpr or e instanceof UnaryMinusExpr or e instanceof MinExpr or @@ -365,8 +382,8 @@ private float getTruncatedLowerBounds(Expr expr) { then // If the expression evaluates to a constant, then there is no // need to call getLowerBoundsImpl. - if exists(expr.getValue().toFloat()) - then result = expr.getValue().toFloat() + if exists(getValue(expr).toFloat()) + then result = getValue(expr).toFloat() else ( // Some of the bounds computed by getLowerBoundsImpl might // overflow, so we replace invalid bounds with exprMinVal. @@ -418,8 +435,8 @@ private float getTruncatedUpperBounds(Expr expr) { then // If the expression evaluates to a constant, then there is no // need to call getUpperBoundsImpl. - if exists(expr.getValue().toFloat()) - then result = expr.getValue().toFloat() + if exists(getValue(expr).toFloat()) + then result = getValue(expr).toFloat() else ( // Some of the bounds computed by `getUpperBoundsImpl` // might overflow, so we replace invalid bounds with diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test.c index 88fe22c3b31..5802ca3eb4f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test.c @@ -69,3 +69,10 @@ void test10(int x) { } while (0); } } + +extern const int const256; + +void test11() { + short s; + for(s = 0; s < const256; ++s) {} +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test2.c b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test2.c new file mode 100644 index 00000000000..7a9609c9a3b --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/wider_type/test2.c @@ -0,0 +1 @@ +const int const256 = 256; \ No newline at end of file