Skip to content

Commit 38cf430

Browse files
Import INT50-CPP into 4-1-3
1 parent d7d4769 commit 38cf430

File tree

13 files changed

+140
-43
lines changed

13 files changed

+140
-43
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `INT50-CPP` - `DoNotCastToAnOutOfRangeEnumerationValue.ql`:
2+
- Refactored query logic into a shared library (`DoNotCastToAnOutOfRangeEnumerationValueShared.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/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.ql

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,12 @@
1818

1919
import cpp
2020
import codingstandards.cpp.cert
21-
import codingstandards.cpp.Enums
22-
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
23-
import codingstandards.cpp.SimpleRangeAnalysisCustomizations
21+
import codingstandards.cpp.rules.donotcasttoanoutofrangeenumerationvalueshared.DoNotCastToAnOutOfRangeEnumerationValueShared
2422

25-
from Cast c, Enum e, string description
26-
where
27-
not isExcluded(c, TypeRangesPackage::doNotCastToAnOutOfRangeEnumerationValueQuery()) and
28-
// Conversion from an integral type to an enum type
29-
c.getExpr().getType().getUnspecifiedType() instanceof IntegralType and
30-
c.getType().getUnspecifiedType() = e and
31-
not (
32-
// The deduced bound for the expression is within the type range for the explicit type
33-
upperBound(c.getExpr()) <= Enums::getValueRangeUpperBound(e) and
34-
lowerBound(c.getExpr()) >= Enums::getValueRangeLowerBound(e)
35-
) and
36-
// Not a compile time constant with the same value as an existing enum constant
37-
not exists(float enumConstantValue |
38-
enumConstantValue = Enums::getEnumConstantValue(e.getAnEnumConstant())
39-
|
40-
// Expression is a constant
41-
c.getExpr().getValue().toFloat() = enumConstantValue
42-
or
43-
// Range analysis has precise bounds
44-
enumConstantValue = upperBound(c.getExpr()) and
45-
enumConstantValue = lowerBound(c.getExpr())
46-
) and
47-
(
48-
if exists(upperBound(c.getExpr()))
49-
then
50-
description =
51-
"Cast to enum $@ with value range " + Enums::getValueRangeLowerBound(e) + "..." +
52-
Enums::getValueRangeUpperBound(e) + " from expression with wider value range " +
53-
lowerBound(c.getExpr()) + "..." + upperBound(c.getExpr()) + " in function " +
54-
c.getEnclosingFunction().getName() + "."
55-
else
56-
description =
57-
"Cast to enum $@ with value range " + Enums::getValueRangeLowerBound(e) + "..." +
58-
Enums::getValueRangeUpperBound(e) +
59-
" from expression with a potentially wider value range."
60-
)
61-
select c, description, e, e.getName()
23+
module DoNotCastToAnOutOfRangeEnumerationValueConfig implements
24+
DoNotCastToAnOutOfRangeEnumerationValueSharedConfigSig
25+
{
26+
Query getQuery() { result = TypeRangesPackage::doNotCastToAnOutOfRangeEnumerationValueQuery() }
27+
}
28+
29+
import DoNotCastToAnOutOfRangeEnumerationValueShared<DoNotCastToAnOutOfRangeEnumerationValueConfig>

cpp/cert/test/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.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+
cpp/common/test/rules/donotcasttoanoutofrangeenumerationvalueshared/DoNotCastToAnOutOfRangeEnumerationValueShared.ql

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+
TOutOfRangeEnumCastCriticalUnspecifiedBehaviorQuery()
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 `outOfRangeEnumCastCriticalUnspecifiedBehavior` query
62+
UndefinedPackage::outOfRangeEnumCastCriticalUnspecifiedBehaviorQuery() and
63+
queryId =
64+
// `@id` for the `outOfRangeEnumCastCriticalUnspecifiedBehavior` query
65+
"cpp/misra/out-of-range-enum-cast-critical-unspecified-behavior" 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 outOfRangeEnumCastCriticalUnspecifiedBehaviorQuery() {
107+
//autogenerate `Query` type
108+
result =
109+
// `Query` type for `outOfRangeEnumCastCriticalUnspecifiedBehavior` query
110+
TQueryCPP(TUndefinedPackageQuery(TOutOfRangeEnumCastCriticalUnspecifiedBehaviorQuery()))
111+
}
95112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Provides a configurable module DoNotCastToAnOutOfRangeEnumerationValueShared with a `problems` predicate
3+
* for the following issue:
4+
* Casting to an out-of-range enumeration value leads to unspecified or undefined
5+
* behavior.
6+
*/
7+
8+
import cpp
9+
import codingstandards.cpp.Customizations
10+
import codingstandards.cpp.Exclusions
11+
import codingstandards.cpp.Enums
12+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
13+
import codingstandards.cpp.SimpleRangeAnalysisCustomizations
14+
15+
signature module DoNotCastToAnOutOfRangeEnumerationValueSharedConfigSig {
16+
Query getQuery();
17+
}
18+
19+
module DoNotCastToAnOutOfRangeEnumerationValueShared<
20+
DoNotCastToAnOutOfRangeEnumerationValueSharedConfigSig Config>
21+
{
22+
query predicate problems(Cast c, string description, Enum e, string enumName) {
23+
not isExcluded(c, Config::getQuery()) and
24+
// Conversion from an integral type to an enum type
25+
c.getExpr().getType().getUnspecifiedType() instanceof IntegralType and
26+
c.getType().getUnspecifiedType() = e and
27+
not (
28+
// The deduced bound for the expression is within the type range for the explicit type
29+
upperBound(c.getExpr()) <= Enums::getValueRangeUpperBound(e) and
30+
lowerBound(c.getExpr()) >= Enums::getValueRangeLowerBound(e)
31+
) and
32+
// Not a compile time constant with the same value as an existing enum constant
33+
not exists(float enumConstantValue |
34+
enumConstantValue = Enums::getEnumConstantValue(e.getAnEnumConstant())
35+
|
36+
// Expression is a constant
37+
c.getExpr().getValue().toFloat() = enumConstantValue
38+
or
39+
// Range analysis has precise bounds
40+
enumConstantValue = upperBound(c.getExpr()) and
41+
enumConstantValue = lowerBound(c.getExpr())
42+
) and
43+
enumName = e.getName() and
44+
(
45+
if exists(upperBound(c.getExpr()))
46+
then
47+
description =
48+
"Cast to enum $@ with value range " + Enums::getValueRangeLowerBound(e) + "..." +
49+
Enums::getValueRangeUpperBound(e) + " from expression with wider value range " +
50+
lowerBound(c.getExpr()) + "..." + upperBound(c.getExpr()) + " in function " +
51+
c.getEnclosingFunction().getName() + "."
52+
else
53+
description =
54+
"Cast to enum $@ with value range " + Enums::getValueRangeLowerBound(e) + "..." +
55+
Enums::getValueRangeUpperBound(e) +
56+
" from expression with a potentially wider value range."
57+
)
58+
}
59+
}

cpp/cert/test/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue.expected renamed to cpp/common/test/rules/donotcasttoanoutofrangeenumerationvalueshared/DoNotCastToAnOutOfRangeEnumerationValueShared.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
| test.cpp:9:11:9:16 | (Foo)... | Cast to enum $@ with value range 0...3 from expression with wider value range -2147483648...2147483647 in function test_unconstrained_cast. | test.cpp:3:6:3:8 | Foo | Foo |
22
| test.cpp:15:13:15:18 | (Foo)... | Cast to enum $@ with value range 0...3 from expression with wider value range 0...2147483647 in function test_range_check. | test.cpp:3:6:3:8 | Foo | Foo |
33
| test.cpp:20:16:20:21 | (Foo)... | Cast to enum $@ with value range 0...3 from expression with wider value range 0...4 in function test_range_check. | test.cpp:3:6:3:8 | Foo | Foo |
4-
| test.cpp:27:12:27:25 | (Foo)... | Cast to enum $@ with value range 0...3 from expression with wider value range 0...7 in function test_unsanitize. | test.cpp:3:6:3:8 | Foo | Foo |
4+
| test.cpp:27:12:27:25 | (Foo)... | Cast to enum $@ with value range 0...3 from expression with wider value range 0...7 in function test_unsanitize. | test.cpp:3:6:3:8 | Foo | Foo |
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.donotcasttoanoutofrangeenumerationvalueshared.DoNotCastToAnOutOfRangeEnumerationValueShared
3+
4+
module TestFileConfig implements DoNotCastToAnOutOfRangeEnumerationValueSharedConfigSig {
5+
Query getQuery() { result instanceof TestQuery }
6+
}
7+
8+
import DoNotCastToAnOutOfRangeEnumerationValueShared<TestFileConfig>

cpp/cert/test/rules/INT50-CPP/test.cpp renamed to cpp/common/test/rules/donotcasttoanoutofrangeenumerationvalueshared/test.cpp

File renamed without changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @id cpp/misra/out-of-range-enum-cast-critical-unspecified-behavior
3+
* @name RULE-4-1-3: Out-of-range enumeration cast leads to critical unspecified behavior
4+
* @description Casting to an enumeration value outside the range of the enumeration's values
5+
* results in critical unspecified behavior.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-4-1-3
10+
* correctness
11+
* scope/system
12+
* external/misra/enforcement/undecidable
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
import codingstandards.cpp.rules.donotcasttoanoutofrangeenumerationvalueshared.DoNotCastToAnOutOfRangeEnumerationValueShared
19+
20+
module OutOfRangeEnumCastCriticalUnspecifiedBehaviorConfig implements
21+
DoNotCastToAnOutOfRangeEnumerationValueSharedConfigSig
22+
{
23+
Query getQuery() {
24+
result = UndefinedPackage::outOfRangeEnumCastCriticalUnspecifiedBehaviorQuery()
25+
}
26+
}
27+
28+
import DoNotCastToAnOutOfRangeEnumerationValueShared<OutOfRangeEnumCastCriticalUnspecifiedBehaviorConfig>

0 commit comments

Comments
 (0)