Skip to content

Commit bf1c4ce

Browse files
authored
Merge branch 'main' into lcartey/rule-11-4-improvements
2 parents 0628e50 + 2db3484 commit bf1c4ce

21 files changed

+416
-225
lines changed

c/misra/src/codingstandards/c/misra/EssentialTypes.qll

+15-7
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ class EssentialBinaryLogicalOperationExpr extends EssentialExpr, BinaryLogicalOp
179179
override Type getEssentialType() { result instanceof BoolType }
180180
}
181181

182+
class EssentialUnaryLogicalOperationExpr extends EssentialExpr, UnaryLogicalOperation {
183+
override Type getEssentialType() { result instanceof BoolType }
184+
}
185+
182186
class EssentialEqualityOperationExpr extends EssentialExpr, EqualityOperation {
183187
override Type getEssentialType() { result instanceof BoolType }
184188
}
@@ -355,13 +359,17 @@ class EssentialLiteral extends EssentialExpr, Literal {
355359
else (
356360
if this.(CharLiteral).getCharacter().length() = 1
357361
then result instanceof PlainCharType
358-
else (
359-
getStandardType().(IntegralType).isSigned() and
360-
result = stlr(this)
361-
or
362-
not getStandardType().(IntegralType).isSigned() and
363-
result = utlr(this)
364-
)
362+
else
363+
exists(Type underlyingStandardType |
364+
underlyingStandardType = getStandardType().getUnderlyingType()
365+
|
366+
if underlyingStandardType instanceof IntType
367+
then
368+
if underlyingStandardType.(IntType).isSigned()
369+
then result = stlr(this)
370+
else result = utlr(this)
371+
else result = underlyingStandardType
372+
)
365373
)
366374
}
367375
}

c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql

+4-3
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ predicate isInappropriateEssentialType(
178178
child =
179179
[
180180
operator.(BinaryBitwiseOperation).getAnOperand(),
181-
operator.(Bitwise::AssignBitwiseOperation).getAnOperand()
181+
operator.(Bitwise::AssignBitwiseOperation).getAnOperand(),
182+
operator.(ComplementExpr).getAnOperand()
182183
] and
183184
not operator instanceof LShiftExpr and
184185
not operator instanceof RShiftExpr and
@@ -240,7 +241,7 @@ string getRationaleMessage(int rationaleId, EssentialTypeCategory etc) {
240241
result = "Bitwise operator applied to operand of " + etc + " and not essentially unsigned."
241242
or
242243
rationaleId = 7 and
243-
result = "Right hand operatand of shift operator is " + etc + " and not not essentially unsigned."
244+
result = "Right hand operand of shift operator is " + etc + " and not not essentially unsigned."
244245
or
245246
rationaleId = 8 and
246247
result =
@@ -251,4 +252,4 @@ from Expr operator, Expr child, int rationaleId, EssentialTypeCategory etc
251252
where
252253
not isExcluded(operator, EssentialTypesPackage::operandsOfAnInappropriateEssentialTypeQuery()) and
253254
isInappropriateEssentialType(operator, child, etc, rationaleId)
254-
select operator, getRationaleMessage(rationaleId, etc)
255+
select child, getRationaleMessage(rationaleId, etc)

c/misra/src/rules/RULE-12-2/RightHandOperandOfAShiftRange.ql

+42-5
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,51 @@ class ShiftExpr extends BinaryBitwiseOperation {
2020
ShiftExpr() { this instanceof LShiftExpr or this instanceof RShiftExpr }
2121
}
2222

23-
from ShiftExpr e, Expr right, int max_val
23+
MacroInvocation getAMacroInvocation(ShiftExpr se) { result.getAnExpandedElement() = se }
24+
25+
Macro getPrimaryMacro(ShiftExpr se) {
26+
exists(MacroInvocation mi |
27+
mi = getAMacroInvocation(se) and
28+
not exists(MacroInvocation otherMi |
29+
otherMi = getAMacroInvocation(se) and otherMi.getParentInvocation() = mi
30+
) and
31+
result = mi.getMacro()
32+
)
33+
}
34+
35+
from
36+
ShiftExpr e, Expr right, int max_val, float lowerBound, float upperBound, Type essentialType,
37+
string extraMessage, Locatable optionalPlaceholderLocation, string optionalPlaceholderMessage
2438
where
2539
not isExcluded(right, Contracts7Package::rightHandOperandOfAShiftRangeQuery()) and
2640
right = e.getRightOperand().getFullyConverted() and
27-
max_val = (8 * getEssentialType(e.getLeftOperand()).getSize()) - 1 and
41+
essentialType = getEssentialType(e.getLeftOperand()) and
42+
max_val = (8 * essentialType.getSize()) - 1 and
43+
upperBound = upperBound(right) and
44+
lowerBound = lowerBound(right) and
45+
(
46+
lowerBound < 0 or
47+
upperBound > max_val
48+
) and
49+
// If this shift happens inside a macro, then report the macro as well
50+
// for easier validation
2851
(
29-
lowerBound(right) < 0 or
30-
upperBound(right) > max_val
52+
if exists(getPrimaryMacro(e))
53+
then
54+
extraMessage = " from expansion of macro $@" and
55+
exists(Macro m |
56+
m = getPrimaryMacro(e) and
57+
optionalPlaceholderLocation = m and
58+
optionalPlaceholderMessage = m.getName()
59+
)
60+
else (
61+
extraMessage = "" and
62+
optionalPlaceholderLocation = e and
63+
optionalPlaceholderMessage = ""
64+
)
3165
)
3266
select right,
33-
"The right hand operand of the shift operator shall lie in the range 0 to " + max_val + "."
67+
"The possible range of the right operand of the shift operator (" + lowerBound + ".." + upperBound
68+
+ ") is outside the the valid shift range (0.." + max_val +
69+
") for the essential type of the left operand (" + essentialType + ")" + extraMessage + ".",
70+
optionalPlaceholderLocation, optionalPlaceholderMessage

c/misra/src/rules/RULE-5-8/IdentifiersWithExternalLinkageNotUnique.ql

+19-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,25 @@ class NotUniqueExternalIdentifier extends ExternalIdentifiers {
4141

4242
Declaration getAConflictingDeclaration() {
4343
not result = this and
44-
isConflictingDeclaration(result, getName())
44+
isConflictingDeclaration(result, getName()) and
45+
// We only consider a declaration to be conflicting if it shares a link target with the external
46+
// identifier. This avoids reporting false positives where multiple binaries or libraries are
47+
// built in the same CodeQL database, but are not intended to be linked together.
48+
exists(LinkTarget lt |
49+
// External declaration can only be a function or global variable
50+
lt = this.(Function).getALinkTarget() or
51+
lt = this.(GlobalVariable).getALinkTarget()
52+
|
53+
lt = result.(Function).getALinkTarget()
54+
or
55+
lt = result.(GlobalVariable).getALinkTarget()
56+
or
57+
exists(Class c | c.getAMember() = result and c.getALinkTarget() = lt)
58+
or
59+
result.(LocalVariable).getFunction().getALinkTarget() = lt
60+
or
61+
result.(Class).getALinkTarget() = lt
62+
)
4563
}
4664
}
4765

c/misra/test/c/misra/EssentialTypes.expected

+35
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,38 @@
3838
| test.c:26:3:26:3 | f | float | float | essentially Floating type |
3939
| test.c:27:3:27:5 | f32 | float32_t | float32_t | essentially Floating type |
4040
| test.c:28:3:28:6 | cf32 | float | float | essentially Floating type |
41+
| test.c:32:3:32:3 | 1 | signed char | signed char | essentially Signed type |
42+
| test.c:33:3:33:4 | 1 | unsigned char | unsigned char | essentially Unsigned type |
43+
| test.c:34:3:34:5 | 1 | unsigned long | unsigned long | essentially Unsigned type |
44+
| test.c:38:13:38:16 | 1 | bool | bool | essentially Boolean type |
45+
| test.c:38:13:38:16 | (bool)... | bool | bool | essentially Boolean type |
46+
| test.c:39:20:39:20 | 1 | signed char | signed char | essentially Signed type |
47+
| test.c:39:20:39:20 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type |
48+
| test.c:40:23:40:23 | 1 | signed char | signed char | essentially Signed type |
49+
| test.c:40:23:40:23 | (unsigned short)... | unsigned short | unsigned short | essentially Unsigned type |
50+
| test.c:41:17:41:18 | 1 | signed char | signed char | essentially Signed type |
51+
| test.c:42:21:42:21 | 1 | signed char | signed char | essentially Signed type |
52+
| test.c:42:21:42:21 | (signed short)... | signed short | signed short | essentially Signed type |
53+
| test.c:44:3:44:4 | ! ... | bool | bool | essentially Boolean type |
54+
| test.c:44:4:44:4 | b | bool | bool | essentially Boolean type |
55+
| test.c:45:3:45:4 | ! ... | bool | bool | essentially Boolean type |
56+
| test.c:45:4:45:4 | u | unsigned int | unsigned int | essentially Unsigned type |
57+
| test.c:46:3:46:5 | ! ... | bool | bool | essentially Boolean type |
58+
| test.c:46:4:46:5 | us | unsigned short | unsigned short | essentially Unsigned type |
59+
| test.c:47:3:47:4 | ! ... | bool | bool | essentially Boolean type |
60+
| test.c:47:4:47:4 | s | signed int | signed int | essentially Signed type |
61+
| test.c:48:3:48:5 | ! ... | bool | bool | essentially Boolean type |
62+
| test.c:48:4:48:5 | ss | signed short | signed short | essentially Signed type |
63+
| test.c:50:3:50:4 | ~ ... | int | int | essentially Signed type |
64+
| test.c:50:4:50:4 | (int)... | int | int | essentially Signed type |
65+
| test.c:50:4:50:4 | b | bool | bool | essentially Boolean type |
66+
| test.c:51:3:51:4 | ~ ... | unsigned int | unsigned int | essentially Unsigned type |
67+
| test.c:51:4:51:4 | u | unsigned int | unsigned int | essentially Unsigned type |
68+
| test.c:52:3:52:5 | ~ ... | unsigned short | unsigned short | essentially Unsigned type |
69+
| test.c:52:4:52:5 | (int)... | int | int | essentially Signed type |
70+
| test.c:52:4:52:5 | us | unsigned short | unsigned short | essentially Unsigned type |
71+
| test.c:53:3:53:4 | ~ ... | signed int | signed int | essentially Signed type |
72+
| test.c:53:4:53:4 | s | signed int | signed int | essentially Signed type |
73+
| test.c:54:3:54:5 | ~ ... | int | int | essentially Signed type |
74+
| test.c:54:4:54:5 | (int)... | int | int | essentially Signed type |
75+
| test.c:54:4:54:5 | ss | signed short | signed short | essentially Signed type |

c/misra/test/c/misra/test.c

+26
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,30 @@ void testCategoriesForComplexTypes() {
2626
f; // Should be essentially Floating type
2727
f32; // Should be essentially Floating type
2828
cf32; // Should be essentially Floating type
29+
}
30+
31+
void testConstants() {
32+
1; // Essentially signed char
33+
1U; // Essentially unsigned char
34+
1UL; // Essentially unsigned long
35+
}
36+
37+
void testUnary() {
38+
_Bool b = true;
39+
unsigned int u = 1;
40+
unsigned short us = 1;
41+
signed int s = 1;
42+
signed short ss = 1;
43+
44+
!b; // Should be boolean
45+
!u; // Should be boolean
46+
!us; // Should be boolean
47+
!s; // Should be boolean
48+
!ss; // Should be boolean
49+
50+
~b; // Should be essentially signed
51+
~u; // Should be essentially unsigned
52+
~us; // Should be essentially unsigned
53+
~s; // Should be essentially signed
54+
~ss; // Should be essentially signed
2955
}

0 commit comments

Comments
 (0)