Skip to content

Commit ea7d168

Browse files
committed
MISRA C++ StandardConversions - improve detection of bitfield types
1 parent af2ff95 commit ea7d168

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

cpp/misra/src/codingstandards/cpp/misra/StandardConversions.qll

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,17 @@ class NumericType extends Type {
5454
}
5555

5656
predicate isAssignment(Expr source, NumericType targetType, string context) {
57-
// Assignment operator (but not compound assignment)
57+
// Assignment expression (which excludes compound assignments)
5858
exists(AssignExpr assign |
5959
assign.getRValue() = source and
6060
context = "assignment"
6161
|
62-
// TODO generalize to variable init (do we need this for bitfields?) and extract
6362
if isAssignedToBitfield(source, _)
6463
then
64+
// For the MISRA type rules we treat bit fields as a special case
6565
exists(BitField bf |
6666
isAssignedToBitfield(source, bf) and
67-
// TODO integral after numeric?
68-
targetType.(IntegralType).(NumericType).getSignedness() =
69-
bf.getType().(NumericType).getSignedness() and
70-
// smallest integral type that can hold the bit field value
71-
targetType.getRealSize() * 8 >= bf.getNumBits() and
72-
not exists(IntegralType other |
73-
other.getSize() * 8 >= bf.getNumBits() and
74-
other.(NumericType).getSignedness() = targetType.getSignedness() and
75-
other.getSize() < targetType.getRealSize()
76-
)
67+
targetType = getBitFieldType(bf)
7768
)
7869
else targetType = assign.getLValue().getType()
7970
)
@@ -82,8 +73,14 @@ predicate isAssignment(Expr source, NumericType targetType, string context) {
8273
exists(Variable v, Initializer init |
8374
init.getExpr() = source and
8475
v.getInitializer() = init and
85-
targetType = v.getType() and
8676
context = "initialization"
77+
|
78+
// For the MISRA type rules we treat bit fields as a special case
79+
if v instanceof BitField
80+
then targetType = getBitFieldType(v)
81+
else
82+
// Regular variable initialization
83+
targetType = v.getType()
8784
)
8885
or
8986
// Passing a function parameter by value
@@ -117,6 +114,30 @@ predicate isAssignment(Expr source, NumericType targetType, string context) {
117114
)
118115
}
119116

117+
/**
118+
* Gets the smallest integral type that can hold the value of a bit field.
119+
*
120+
* The type is determined by the signedness of the bit field and the number of bits.
121+
*/
122+
NumericType getBitFieldType(BitField bf) {
123+
exists(NumericType bitfieldActualType |
124+
bitfieldActualType = bf.getType() and
125+
// Integral type with the same signedness as the bit field, and big enough to hold the bit field value
126+
result instanceof IntegralType and
127+
result.getSignedness() = bitfieldActualType.getSignedness() and
128+
result.getSize() * 8 >= bf.getNumBits() and
129+
// No smaller integral type can hold the bit field value
130+
not exists(IntegralType other |
131+
other.getSize() * 8 >= bf.getNumBits() and
132+
other.(NumericType).getSignedness() = result.getSignedness() and
133+
other.getSize() < result.getRealSize()
134+
)
135+
)
136+
}
137+
138+
/**
139+
* Holds if the `source` expression is assigned to a bit field.
140+
*/
120141
predicate isAssignedToBitfield(Expr source, BitField bf) {
121142
exists(Assignment assign |
122143
assign.getRValue() = source and

0 commit comments

Comments
 (0)