Skip to content

Commit 23065e4

Browse files
committed
IntegerOverflow: Create an overflow library
Enable re-use of existing query by extracting out "InterestingBinaryOverflowingExpr" to a separate library.
1 parent 4a04ff2 commit 23065e4

File tree

2 files changed

+69
-60
lines changed

2 files changed

+69
-60
lines changed

cpp/autosar/src/rules/A4-7-1/IntegerExpressionLeadToDataLoss.ql

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,69 +15,10 @@
1515

1616
import cpp
1717
import codingstandards.cpp.autosar
18-
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
18+
import codingstandards.cpp.Overflow
1919
import semmle.code.cpp.controlflow.Guards
20-
import semmle.code.cpp.dataflow.TaintTracking
2120
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
2221

23-
/**
24-
* A `BinaryArithmeticOperation` which may overflow and is a potentially interesting case to review
25-
* that is not covered by other queries for this rule.
26-
*/
27-
class InterestingBinaryOverflowingExpr extends BinaryArithmeticOperation {
28-
InterestingBinaryOverflowingExpr() {
29-
// Might overflow or underflow
30-
(
31-
exprMightOverflowNegatively(this)
32-
or
33-
exprMightOverflowPositively(this)
34-
) and
35-
not this.isAffectedByMacro() and
36-
// Ignore pointer arithmetic
37-
not this instanceof PointerArithmeticOperation and
38-
// Covered by `IntMultToLong.ql` instead
39-
not this instanceof MulExpr and
40-
// Not covered by this query - overflow/underflow in division is rare
41-
not this instanceof DivExpr
42-
}
43-
44-
/**
45-
* Get a `GVN` which guards this expression which may overflow.
46-
*/
47-
GVN getAGuardingGVN() {
48-
exists(GuardCondition gc, Expr e |
49-
not gc = getABadOverflowCheck() and
50-
TaintTracking::localTaint(DataFlow::exprNode(e), DataFlow::exprNode(gc.getAChild*())) and
51-
gc.controls(this.getBasicBlock(), _) and
52-
result = globalValueNumber(e)
53-
)
54-
}
55-
56-
/**
57-
* Identifies a bad overflow check for this overflow expression.
58-
*/
59-
GuardCondition getABadOverflowCheck() {
60-
exists(AddExpr ae, RelationalOperation relOp |
61-
this = ae and
62-
result = relOp and
63-
// Looking for this pattern:
64-
// if (x + y > x)
65-
// use(x + y)
66-
//
67-
globalValueNumber(relOp.getAnOperand()) = globalValueNumber(ae) and
68-
globalValueNumber(relOp.getAnOperand()) = globalValueNumber(ae.getAnOperand())
69-
|
70-
// Signed overflow checks are insufficient
71-
ae.getUnspecifiedType().(IntegralType).isSigned()
72-
or
73-
// Unsigned overflow checks can still be bad, if the result is promoted.
74-
forall(Expr op | op = ae.getAnOperand() | op.getType().getSize() < any(IntType i).getSize()) and
75-
// Not explicitly converted to a smaller type before the comparison
76-
not ae.getExplicitlyConverted().getType().getSize() < any(IntType i).getSize()
77-
)
78-
}
79-
}
80-
8122
from InterestingBinaryOverflowingExpr e
8223
where
8324
not isExcluded(e, IntegerConversionPackage::integerExpressionLeadToDataLossQuery()) and
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* This module provides predicates for checking whether an operation overflows or wraps.
3+
*/
4+
5+
import cpp
6+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
7+
import SimpleRangeAnalysisCustomizations
8+
import semmle.code.cpp.controlflow.Guards
9+
import semmle.code.cpp.dataflow.TaintTracking
10+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
11+
12+
/**
13+
* A `BinaryArithmeticOperation` which may overflow and is a potentially interesting case to review
14+
* that is not covered by other queries for this rule.
15+
*/
16+
class InterestingBinaryOverflowingExpr extends BinaryArithmeticOperation {
17+
InterestingBinaryOverflowingExpr() {
18+
// Might overflow or underflow
19+
(
20+
exprMightOverflowNegatively(this)
21+
or
22+
exprMightOverflowPositively(this)
23+
) and
24+
not this.isAffectedByMacro() and
25+
// Ignore pointer arithmetic
26+
not this instanceof PointerArithmeticOperation and
27+
// Covered by `IntMultToLong.ql` instead
28+
not this instanceof MulExpr and
29+
// Not covered by this query - overflow/underflow in division is rare
30+
not this instanceof DivExpr
31+
}
32+
33+
/**
34+
* Get a `GVN` which guards this expression which may overflow.
35+
*/
36+
GVN getAGuardingGVN() {
37+
exists(GuardCondition gc, Expr e |
38+
not gc = getABadOverflowCheck() and
39+
TaintTracking::localTaint(DataFlow::exprNode(e), DataFlow::exprNode(gc.getAChild*())) and
40+
gc.controls(this.getBasicBlock(), _) and
41+
result = globalValueNumber(e)
42+
)
43+
}
44+
45+
/**
46+
* Identifies a bad overflow check for this overflow expression.
47+
*/
48+
GuardCondition getABadOverflowCheck() {
49+
exists(AddExpr ae, RelationalOperation relOp |
50+
this = ae and
51+
result = relOp and
52+
// Looking for this pattern:
53+
// if (x + y > x)
54+
// use(x + y)
55+
//
56+
globalValueNumber(relOp.getAnOperand()) = globalValueNumber(ae) and
57+
globalValueNumber(relOp.getAnOperand()) = globalValueNumber(ae.getAnOperand())
58+
|
59+
// Signed overflow checks are insufficient
60+
ae.getUnspecifiedType().(IntegralType).isSigned()
61+
or
62+
// Unsigned overflow checks can still be bad, if the result is promoted.
63+
forall(Expr op | op = ae.getAnOperand() | op.getType().getSize() < any(IntType i).getSize()) and
64+
// Not explicitly converted to a smaller type before the comparison
65+
not ae.getExplicitlyConverted().getType().getSize() < any(IntType i).getSize()
66+
)
67+
}
68+
}

0 commit comments

Comments
 (0)