Skip to content

Commit 8223495

Browse files
Add critical unspecified behavior for signed integer overflow
1 parent d7d4769 commit 8223495

File tree

16 files changed

+346
-23
lines changed

16 files changed

+346
-23
lines changed

c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,10 @@
1919

2020
import cpp
2121
import codingstandards.c.cert
22-
import codingstandards.cpp.Overflow
23-
import semmle.code.cpp.controlflow.Guards
24-
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
22+
import codingstandards.cpp.rules.signedintegeroverflowshared.SignedIntegerOverflowShared
2523

26-
from InterestingOverflowingOperation op
27-
where
28-
not isExcluded(op, IntegerOverflowPackage::signedIntegerOverflowQuery()) and
29-
(
30-
// An operation that returns a signed integer type
31-
op.getType().getUnderlyingType().(IntegralType).isSigned()
32-
or
33-
// The divide or rem expression on a signed integer
34-
op.(DivOrRemOperation).getDividend().getType().getUnderlyingType().(IntegralType).isSigned()
35-
) and
36-
// Not checked before the operation
37-
not op.hasValidPreCheck() and
38-
// Covered by INT34-C
39-
not op instanceof LShiftExpr
40-
select op,
41-
"Operation " + op.getOperator() + " of type " + op.getType().getUnderlyingType() +
42-
" may overflow or underflow."
24+
module SignedIntegerOverflowConfig implements SignedIntegerOverflowSharedConfigSig {
25+
Query getQuery() { result = IntegerOverflowPackage::signedIntegerOverflowQuery() }
26+
}
27+
28+
import SignedIntegerOverflowShared<SignedIntegerOverflowConfig>

c/cert/test/rules/INT32-C/SignedIntegerOverflow.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/signedintegeroverflowshared/SignedIntegerOverflowShared.ql

c/cert/test/rules/INT32-C/SignedIntegerOverflow.expected renamed to c/common/test/rules/signedintegeroverflowshared/SignedIntegerOverflowShared.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
| test.c:147:5:147:12 | ... %= ... | Operation %= of type signed int may overflow or underflow. |
2222
| test.c:161:3:161:5 | - ... | Operation - of type signed int may overflow or underflow. |
2323
| test.c:173:3:173:6 | ... ++ | Operation ++ of type signed int may overflow or underflow. |
24-
| test.c:189:3:189:6 | ... -- | Operation -- of type signed int may overflow or underflow. |
24+
| test.c:189:3:189:6 | ... -- | Operation -- of type signed int may overflow or underflow. |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.signedintegeroverflowshared.SignedIntegerOverflowShared
3+
4+
module TestFileConfig implements SignedIntegerOverflowSharedConfigSig {
5+
Query getQuery() { result instanceof TestQuery }
6+
}
7+
8+
import SignedIntegerOverflowShared<TestFileConfig>

c/cert/test/rules/INT32-C/test.c renamed to c/common/test/rules/signedintegeroverflowshared/test.c

File renamed without changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `INT32-C` - `SignedIntegerOverflow.ql`:
2+
- Refactored query logic into a shared library (`SignedIntegerOverflowShared.qll`) to enable reuse by MISRA C++ `RULE-4-1-3`. The query logic is unchanged and no visible changes to results or performance are expected.

cpp/common/src/codingstandards/cpp/exclusions/cpp/Undefined.qll

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ newtype UndefinedQuery =
88
TCriticalUnspecifiedBehaviorQuery() or
99
TUndefinedBehaviorAuditQuery() or
1010
TCriticalUnspecifiedBehaviorAuditQuery() or
11-
TPossibleDataRaceBetweenThreadsQuery()
11+
TPossibleDataRaceBetweenThreadsQuery() or
12+
TSignedIntegerOverflowQuery()
1213

1314
predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, string category) {
1415
query =
@@ -55,6 +56,15 @@ predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, s
5556
"cpp/misra/possible-data-race-between-threads" and
5657
ruleId = "RULE-4-1-3" and
5758
category = "required"
59+
or
60+
query =
61+
// `Query` instance for the `signedIntegerOverflow` query
62+
UndefinedPackage::signedIntegerOverflowQuery() and
63+
queryId =
64+
// `@id` for the `signedIntegerOverflow` query
65+
"cpp/misra/signed-integer-overflow" and
66+
ruleId = "RULE-4-1-3" and
67+
category = "required"
5868
}
5969

6070
module UndefinedPackage {
@@ -92,4 +102,11 @@ module UndefinedPackage {
92102
// `Query` type for `possibleDataRaceBetweenThreads` query
93103
TQueryCPP(TUndefinedPackageQuery(TPossibleDataRaceBetweenThreadsQuery()))
94104
}
105+
106+
Query signedIntegerOverflowQuery() {
107+
//autogenerate `Query` type
108+
result =
109+
// `Query` type for `signedIntegerOverflow` query
110+
TQueryCPP(TUndefinedPackageQuery(TSignedIntegerOverflowQuery()))
111+
}
95112
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Provides a configurable module SignedIntegerOverflowShared with a `problems` predicate
3+
* for the following issue:
4+
* The multiplication of two signed integers can lead to underflow or overflow and
5+
* therefore undefined behavior.
6+
*/
7+
8+
import cpp
9+
import codingstandards.cpp.Customizations
10+
import codingstandards.cpp.Exclusions
11+
import codingstandards.cpp.Overflow
12+
import semmle.code.cpp.controlflow.Guards
13+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
14+
15+
signature module SignedIntegerOverflowSharedConfigSig {
16+
Query getQuery();
17+
}
18+
19+
module SignedIntegerOverflowShared<SignedIntegerOverflowSharedConfigSig Config> {
20+
query predicate problems(InterestingOverflowingOperation op, string message) {
21+
not isExcluded(op, Config::getQuery()) and
22+
(
23+
// An operation that returns a signed integer type
24+
op.getType().getUnderlyingType().(IntegralType).isSigned()
25+
or
26+
// The divide or rem expression on a signed integer
27+
op.(DivOrRemOperation).getDividend().getType().getUnderlyingType().(IntegralType).isSigned()
28+
) and
29+
// Not checked before the operation
30+
not op.hasValidPreCheck() and
31+
// Left shift overflow is covered by separate queries (e.g. INT34-C)
32+
not op instanceof LShiftExpr and
33+
message =
34+
"Operation " + op.getOperator() + " of type " + op.getType().getUnderlyingType() +
35+
" may overflow or underflow."
36+
}
37+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
| test.cpp:6:3:6:9 | ... + ... | Operation + of type int may overflow or underflow. |
2+
| test.cpp:7:3:7:10 | ... += ... | Operation += of type signed int may overflow or underflow. |
3+
| test.cpp:22:7:22:13 | ... + ... | Operation + of type int may overflow or underflow. |
4+
| test.cpp:25:5:25:11 | ... + ... | Operation + of type int may overflow or underflow. |
5+
| test.cpp:26:5:26:12 | ... += ... | Operation += of type signed int may overflow or underflow. |
6+
| test.cpp:31:19:31:25 | ... + ... | Operation + of type int may overflow or underflow. |
7+
| test.cpp:36:3:36:10 | ... += ... | Operation += of type signed int may overflow or underflow. |
8+
| test.cpp:43:3:43:9 | ... - ... | Operation - of type int may overflow or underflow. |
9+
| test.cpp:44:3:44:10 | ... -= ... | Operation -= of type signed int may overflow or underflow. |
10+
| test.cpp:58:19:58:25 | ... - ... | Operation - of type int may overflow or underflow. |
11+
| test.cpp:62:3:62:10 | ... -= ... | Operation -= of type signed int may overflow or underflow. |
12+
| test.cpp:69:3:69:8 | ... * ... | Operation * of type int may overflow or underflow. |
13+
| test.cpp:70:3:70:10 | ... *= ... | Operation *= of type signed int may overflow or underflow. |
14+
| test.cpp:115:3:115:9 | ... / ... | Operation / of type int may overflow or underflow. |
15+
| test.cpp:116:3:116:10 | ... /= ... | Operation /= of type signed int may overflow or underflow. |
16+
| test.cpp:123:5:123:11 | ... / ... | Operation / of type int may overflow or underflow. |
17+
| test.cpp:124:5:124:12 | ... /= ... | Operation /= of type signed int may overflow or underflow. |
18+
| test.cpp:138:3:138:9 | ... % ... | Operation % of type int may overflow or underflow. |
19+
| test.cpp:139:3:139:10 | ... %= ... | Operation %= of type signed int may overflow or underflow. |
20+
| test.cpp:146:5:146:11 | ... % ... | Operation % of type int may overflow or underflow. |
21+
| test.cpp:147:5:147:12 | ... %= ... | Operation %= of type signed int may overflow or underflow. |
22+
| test.cpp:161:3:161:5 | - ... | Operation - of type signed int may overflow or underflow. |
23+
| test.cpp:173:3:173:6 | ... ++ | Operation ++ of type signed int may overflow or underflow. |
24+
| test.cpp:189:3:189:6 | ... -- | Operation -- of type signed int may overflow or underflow. |

0 commit comments

Comments
 (0)